先来介绍一下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

posted on 2018-03-21 22:08  爬虫一只  阅读(241)  评论(0编辑  收藏  举报