React Mixins Are Dead in ES6

背景

Unfortunately, we will not launch any mixin support for ES6 classes in React. That would defeat the purpose of only using idiomatic JavaScript concepts.
There is no standard and universal way to define mixins in JavaScript. In fact, several features to support mixins were dropped from ES6 today. There are a lot of libraries with different semantics. We think that there should be one way of defining mixins that you can use for any JavaScript class. React just making another doesn’t help that effort.javascript

React官网 文档 v0.13 上咱们能够看到,mixin 再也不被ES6 所支持,但愿以更加通用和标准的javascript 概念去取代它。html

关于Mixins

不少时候,不一样的组件可能须要使用到一些公共的方法,Minxins 能够包装这些公共的方法暴露给外部调用。不少状况下,咱们会定义一些React生命周期的方法,React 会自动地帮咱们把这些方法合并到component 内,这些方法也将被组件所调用。java

可是,使用Mixins也会致使一些问题,主要有如下几个缘由。react

  • 组件和Mixins 之间的关系式隐式的,Mixins 的内部实现一般都会依赖组件内定义的方法,但对于Mixins 来讲,很难知道该方法被定义在哪一个组件中。git

  • 若是一个组件中使用了多个Mixins,而不一样Mixins却定义了相同的方法,这个时候就容易引发冲突。github

  • Mixins 尝试往你的组件中添加更多的state,然而这并非你想要的。 可参考 Why Flux Component is better than Flux Mixin ide

Higher-Order Components

Higher-Order Components是其中一种替代 Mixins 的其中一种解决方案,如今咱们先来看一个 用 mixins 实现的触发 Flux Stores更新 State 的例子。函数

javascriptfunction StoreMixin(...stores) {
  var Mixin = {
    getInitialState() {
      return this.getStateFromStores(this.props);
    },
    componentDidMount() {
      stores.forEach(store =>
        store.addChangeListener(this.handleStoresChanged)
      );
      this.setState(this.getStateFromStores(this.props));
    },
    componentWillUnmount() {
      stores.forEach(store =>
        store.removeChangeListener(this.handleStoresChanged)
      );
    },
    handleStoresChanged() {
      if (this.isMounted()) {
        this.setState(this.getStateFromStores(this.props));
      }
    }
  };
  return Mixin;
}

在使用的时候,咱们先把 StoreMixin 添加到mixins列表中,而后在组件中定义 getStateFromStores(props) 方法ui

javascriptvar UserProfilePage = React.createClass({
  mixins: [StoreMixin(UserStore)],
  propTypes: {
    userId: PropTypes.number.isRequired
  },
  getStateFromStores(props) {
    return {
      user: UserStore.get(props.userId);
    }
  }
  render() {
    var { user } = this.state;
    return <div>{user ? user.name : 'Loading'}</div>;
  }

这样,当UserProfilePage 在渲染的时候就会触发 StoreMixin 中定义的一些生命周期的方法,监听Store数据变化。变化以后触发响应的处理函数。this

什么是 higher-order component ?

higher-order component 是一个接收一个组件,而后返回包装了该组件的另一个新组件的函数。

嗯,听起来有点拗口,咱们来举个例子看看就明白了。

javascriptfunction connectToStores(Component, stores, getStateFromStores) {
  const StoreConnection = React.createClass({
    getInitialState() {
      return getStateFromStores(this.props);
    },
    componentDidMount() {
      stores.forEach(store =>
        store.addChangeListener(this.handleStoresChanged)
      );
    },
    componentWillUnmount() {
      stores.forEach(store =>
        store.removeChangeListener(this.handleStoresChanged)
      );
    },
    handleStoresChanged() {
      if (this.isMounted()) {
        this.setState(getStateFromStores(this.props));
      }
    },
    render() {
      return <Component {...this.props} {...this.state} />;
    }
  });
  return StoreConnection;
};

connectToStores 看起来有点像mixin ,可是和前面的 StoreMixin 不一样。 StoreMixin 管理的是组件的内部 state。可是 connectToStores 倒是把(Comment)组件包装起来,而后把props传递给它。这样,经过一种组件内嵌的良好方式,就把组件的生命周期隔离起来,不存在合并的问题。

推荐

ract-dnd 一个专一于控件拖拽的库,是基于 higher-order component 而实现。

相关文章
相关标签/搜索