『译』React Mixin 的运用

update: Mixin 只适用于 ES5。假如你的项目内里用的是 ES6 ,可以采纳高阶组件来完成 Mixin 的功用。

我运用 React.js 构建大型项目已经有一段时刻了,我遇到过很多在差别的组件中都要用到雷同功用的状况。因而,我花了一个小时摆布的时刻去相识mixin的用法,然后分享我所进修到的一些东西。

为何运用 Mixin ?

React逃避子类组件,然则我们晓得,随处反复地编写一样的代码是不好的。所以为了将一样的功用添加到多个组件当中,你须要将这些通用的功用包装成一个mixin,然后导入到你的模块中。 可以说,比拟继续罢了,React更喜好这类组合的体式格局。嗯,我也喜好如许。

写一个简朴的 Mixin

如今假定我们在写一个app,我们晓得在某些状况下我们须要在好几个组件当中设置默许的name属性。
如今,我们不再是像之前一样在每一个组件中写多个一样的getDefaultProps要领,我们可以像下面一样定义一个mixin

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

它没什么特别的,就是一个简朴的对象罢了。

到场到 React 组件中

为了运用mixin,我们只须要简朴得在组件中到场mixins属性,然后把适才我们写的mixin包裹成一个数组,将它作为该属性的值即可:

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

React.renderComponent(<ComponentOne />, document.body);

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

反复运用

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

var 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 会跑出非常:

Uncaught 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中的:

var 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

var 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

假如你尝试在差别的处所定义雷同的属性时会涌现下面的非常:

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

设置雷同的要领

在差别的mixin中定义雷同的要领,或许mixin和组件中包括了雷同的要领时,会抛出非常:

var 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要领时抛出的非常一样:

Uncaught 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中的递次从左到右的举行挪用。

实例代码:

var 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");
    },
    ...

控制台将输出:

another 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…

翻译程度有限,文中带有个人明白,若有不适当的处所,请在批评中指出,非常感谢!

    原文作者:MockingBird
    原文地址: https://segmentfault.com/a/1190000003016446
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞