转载

『译』React Mixin 的使用

我使用 React.js 构建大型项目已经有一段时间了,我遇到过很多在不同的组件中都要用到相同功能的情况。因此,我花了一个小时左右的时间去了解 mixin 的用法,然后分享我所学习到的一些东西。

为什么使用 Mixin ?

React 回避子类组件,但是我们知道,到处重复地编写同样的代码是不好的。所以为了将同样的功能添加到多个组件当中,你需要将这些通用的功能包装成一个 mixin ,然后导入到你的模块中。 可以说,相比继承而已, React 更喜欢这种组合的方式。嗯,我也喜欢这样。

写一个简单的 Mixin

现在假设我们在写一个app,我们知道在某些情况下我们需要在好几个组件当中设置默认的 name 属性。

现在,我们不再是像以前一样在每个组件中写多个同样的 getDefaultProps 方法,我们可以像下面一样定义一个 mixin

javascriptvar DefaultNameMixin = {     getDefaultProps: function () {         return {name: "Skippy"};     } }; 

它没什么特殊的,就是一个简单的对象而已。

加入到 React 组件中

为了使用 mixin ,我们只需要简单得在组件中加入 mixins 属性,然后把刚才我们写的 mixin 包裹成一个数组,将它作为该属性的值即可:

javascriptvar ComponentOne = React.createClass({  mixins: [DefaultNameMixin],  render: function() {   return  <h2>Hello {this.props.name}</h2> ;  } }); React.renderComponent(<ComponentOne />, document.body);  

JSFiddle 示例:一个简单的 mixin 例子

重复使用

就像你想象的那样,我们可以在任何其他组件中包含我们的 mixin

javascriptvar ComponentTwo = React.createClass({  mixins: [DefaultNameMixin],  render: function () {   return (    <div>     <h4>{this.props.name}</h4>     <p>Favorite food: {this.props.food}</p>    </div>   );  } });  

JSFiddle 示例:在多个组件中使用同一个 mixin

生命周期方法会被重复调用!

如何你的 mixin 当中包含 生命周期方法 ,不要焦急,你仍然可以在你的组件中使用这些方法,而且它们都会被调用:

JSFiddle 示例:展示了两个 default props 都会被设置

两个 getDefaultProps 方法都将被调用,所以我们可以得到默认为 Skippyname 属性和默认为 Pancakesfood 属性。任何一个生命周期方法或属性都会被顺利地重复调用,但是下面的情况除外:

  • render :包含多个 render 方法是不行的。React 会跑出异常:
plainUncaught Error: Invariant Violation: ReactCompositeComponentInterface:  You are attempting to define `render` on your component more than once.  This conflict may be due to a mixin. 
  • displayName :你多次的对它进行设置是没有问题的,但是,最终的结果只以最后一次设置为准。

需要指出的是, mixin 是可以包含在其他的 mixin 中的:

javascriptvar UselessMixin = {   componentDidMount: function () {   console.log("asdas");   } }; var LolMixin = {  mixins: [UselessMixin] }; var PantsOpinion = React.createClass({  mixins: [LolMixin],  render: function () {    return ( <p>I dislike pants</p> );  } }); React.renderComponent(<PantsOpinion />, document.body);  

程序会在控制台打印出 asdas

包含多个 Mixins

我们的 mixins 要包裹在数组当中,提醒了我们可以在组件中包含多个 mixins

javascriptvar DefaultNameMixin = {  getDefaultProps: function () {   return {name: "Lizie"};  } }; var DefaultFoodMixin = {  getDefaultProps: function () {   return {food: "Pancakes"};  } }; var ComponentTwo = React.createClass({  mixins: [DefaultNameMixin, DefaultFoodMixin],  render: function () {   return ( <div>     <h4>{this.props.name}</h4>     <p>Favorite food: {this.props.food}</p>    </div>   );  } });  

注意事项

这里有几件事需要引起我们的注意,当我们使用 mixins 的时候。 幸运地是,这些看起来并不是什么大问题,下面是我们在实践当中发现的一些问题:

设置相同的 Prop 和 State

如果你尝试在不同的地方定义相同的属性时会出现下面的异常:

plainUncaught Error: Invariant Violation: mergeObjectsWithNoDuplicateKeys():  Tried to merge two objects with the same key: name 

设置相同的方法

在不同的 mixin 中定义相同的方法,或者 mixin 和组件中包含了相同的方法时,会抛出异常:

javascriptvar LogOnMountMixin = {  componentDidMount: function () {   console.log("mixin mount method");   this.logBlah()  },  // add a logBlah method here...  logBlah: function () {   console.log("blah");  } }; var MoreLogOnMountMixin = {  componentDidMount: function () {   console.log("another mixin mount method");  },  // ... and again here.  logBlah: function () {   console.log("something other than blah");  } };  

异常信息同多次定义 rander 方法时抛出的异常一样:

plainUncaught Error: Invariant Violation: ReactCompositeComponentInterface:  You are attempting to define `logBlah` on your component more than once.  This conflict may be due to a mixin. 

多个生命周期方法的调用顺序

如果我们的组件和 mixin 中都包含了相同的生命周期方法的话会怎样呢?

我们的 mixin 方法首先会被调用,然后再是组件的中方法被调用。

那当我们的组件中包含多个 mixin ,而这些 mixin 中又包含相同的生命周期方法时,调用顺序又是如何?

它们会根据 mixins 中的顺序从左到右的进行调用。

实例代码:

javascriptvar LogOnMountMixin = {  componentDidMount: function () {   console.log("mixin mount method");  } }; var MoreLogOnMountMixin = {  componentDidMount: function () {   console.log("another mixin mount method");  } }; var ComponentOne = React.createClass({  mixins: [MoreLogOnMountMixin, LogOnMountMixin],  componentDidMount: function () {   console.log("component one mount method");  },  ... var ComponentTwo = React.createClass({  mixins: [LogOnMountMixin, MoreLogOnMountMixin],  componentDidMount: function () {   console.log("component two mount method");  },  ...  

控制台将输出:

plainanother mixin mount method mixin mount method  component one mount method  mixin mount method another mixin mount method  component two mount method 

总结

Mixin 使你React程序变得更为可重用,It's a Good Thing.

我希望这篇文章能够对你有所帮助,如果有任何反馈,很高兴你能够在twitter上 @veddermatic

原文链接: http://simblestudios.com/blog/development/react-mixins-by-example.html

翻译水平有限,文中带有个人理解,如有不恰当的地方,请在评论中指出,非常感谢!

正文到此结束
Loading...