先来介绍一下mixins(混入)
先来看一段代码:
const mixin = function(obj, mixins) { const newObj = obj; newObj.prototype = Object.create(obj.prototype); for (let prop in mixins) { if (mixins.hasOwnProperty(prop)) { newObj.prototype[prop] = mixins[prop]; } } return newObj; } const BigMixin = { fly: () => { console.log('I can fly'); } }; const Big = function() { console.log('new big'); }; const FlyBig = mixin(Big, BigMixin); const flyBig = new FlyBig(); // 'new big' flyBig.fly(); // 'I can fly'
对于广义的 mixin 方法,就是用赋值的方式将 mixins 对象里的方法都挂载到原对象上,就实现了对对象的混入
在来看看React中的使用方式:
import React from 'react'; import PureRenderMixin from 'react-addons-pure-render-mixin'; React.createClass({ mixins: [PureRenderMixin], render() { return <div>foo</div>; } });
React中的mixins其实就是将一段公共代码提供过React组件使用,减少代码的复用。
现在来说说mixins的弊端:
一、mixins隐含依赖
二、造成命名冲突
三、实际上它可能会越滚越大影响了初衷
由于以上弊端,将mixins进行迁移显的尤为重要
一、最优渲染
var PureRenderMixin = require('react-addons-pure-render-mixin'); var Button = React.createClass({ mixins: [PureRenderMixin], // ... }); 现在使用React.PureComponent
二、重用属性(以下代码都为简写)
var SubscriptionMixin = { componentDidMount: function() { DataSource.addChangeListener(this.handleChange); }, }; var CommentList = React.createClass({ mixins: [SubscriptionMixin], render: function() { } }); 现在使用高阶组件,将组件分成子组件与父组件,子组件关注与渲染逻辑,父组件用来建立重用属性,并使用状态自上到下通过props传递给子组件,最后将父组件转变为一可以传入子组件的函数,大功告成。
function withSubscription(WrappedComponent) { return React.createClass({ getInitialState: function() { return { comments: DataSource.getComments() }; }, componentDidMount: function() { DataSource.addChangeListener(this.handleChange); }, render: function() { // Use JSX spread syntax to pass all props and state down automatically. return <WrappedComponent {...this.props} {...this.state} />; } }); } // Optional change: convert CommentList to a functional component // because it doesn't use lifecycle hooks or state. function CommentList(props) { var comments = props.comments; return ( <div> {comments.map(function(comment) { return <Comment comment={comment} key={comment.id} /> })} </div> ) } module.exports = withSubscription(CommentList);
三、渲染逻辑
多个组件需要相同的渲染逻辑,以前的处理方式是
var RowMixin = { renderHeader: function() { return ( ... ); } }; var UserRow = React.createClass({ mixins: [RowMixin], getHeaderText: function() { return this.props.user.fullName; }, render: function() { return ( <div> {this.renderHeader()} </div> ) } });
现在提倡直接额外新建立一个组件,使用的时候引入就好了
四、上下文
这里提倡通过高阶组件来实现
五、方法工具
以前是将所有方法写到对象中,然后将对象添加到mixins中
现在提倡将所有的方法放到js模块中,然后通过导入该模块,进而调用。
结论:其实通过以上的例子,可以看出,通过createClass的方式创建的组件,将一个对象放入到mixins之后,该组件就继承了对象的所有属性,进而可以直接通过this调用。
参考:https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html