React之Mixin

来源:互联网 发布:淘宝有客服电话 编辑:程序博客网 时间:2024/05/22 07:06

  如果说组件嵌套是垂直方面父组件与子组件之间的协同使用,那么Mixin就是横向组件的抽离,抽离出组件相似的代码。

  Mixin允许我们可以定义在多个组件中公用的方法,是解决代码段重用的最强大工具之一。

这里写图片描述


var SetInterValMixin={            componentWillMount:function(){                this.intervals=[];            },            setInterval:function(){                this.intervals.push(setInterval.apply(null,argument));            },            componentWillUnmount:function(){                this.intervals.map(clearInterval);            }        };        var TickTock=React.createClass({            mixins:[SetInterValMixin],//use the mixin            getInitialState:function(){                return {seconds:0}            }});

  上面一段代码就是Minxin 的基本使用场景,定义了名为SetInterValMixin 的mixin,当在TickTock 组件中使用时,在SetInterValMixin 中定义的componentWillMountcomponentWillUnmount,就可以直接加入TickTock中,其实就和在TickTock 中亲自定义的效果是 一样 的,setInterval 同样如此。

这里写图片描述

下面通过一个小例子来说明mixin的用法,实现效果是这样的:

这里写图片描述

不使用mixin时:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Mixin</title>    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script></head><body>    <div id='demo'></div>    <script type="text/babel">        var BindingExample=React.createClass({            getInitialState:function(){                return{                    text:''                }            },            handleChange:function(event){                this.setState({text:event.target.value})            },            render:function(){                return <div>                <input type="text" placeholder="input" onChange={this.handleChange} />                <p>{this.state.text}</p>                </div>            }        });        ReactDOM.render(            <BindingExample />,            document.getElementById('demo')        );    </script></body></html>

使用mixin:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Mixin</title>    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script></head><body>    <div id='demo'></div>    <script type="text/babel">        var BindingMixin={            handleChange:function(key){                var that=this;                return function(event){                    var newState={};                    newState[key]=event.target.value;                    that.setState(newState);                }            }        }        var BindingExample=React.createClass({            mixins:[BindingMixin],            getInitialState:function(){                return{                    text:''                }            },            render:function(){                return <div>                <input type="text" placeholder="input" onChange={this.handleChange('text')} />                <p>{this.state.text}</p>                </div>            }        });        ReactDOM.render(            <BindingExample />,            document.getElementById('demo')        );    </script></body></html>

这里,我们定义了一个名为BindingMixin 的mixin,封装了handleChange()函数。

注意这一行:var that=this;

  js中,如果一个对象里面存在函数,则在这个函数内部的this的指向,将不再是这个对象,一般来说会是全局global,若是在严格模式下,则指向undefined
  在这个例子中,var that=this;这里面的this指向BindingExample(因为handleChange被放入了BindingExample组件中使用),但是在下一句:

   return function(event){
    var newState={};
    newState[key]=event.target.value;
    that.setState(newState);
   }

  这里的this不再指向BindingExample,为了使得this始终指向BindingExample,则可以在this指向变化之前,将this赋值给一个局部变量,这里是that,那么这个that就将始终指向BindingExample。

还需要注意一点:

newState[key]=event.target.value;that.setState(newState);

这里不能够写成:

that.setState({key:event.target.value});

  因为在js内部,{key:event.target.value}这行代码的意思其实是{“key”:event.target.value},也就是说that.setState({key:event.target.value});这句话其实是给this.state新增了一个’key’属性,并将这个’key’属性复制为event.target.value,而并不是在原先的基础上修改,这种对象声名方式,属性名是无法使用变量的
  而在这里,我们其实是想改变this.state.text的值,而非this.state.key。

现在有了mixin之后,我们想在BindingExample 中新增一个textarea,则mixin还可以继续使用,毫无影响,不需要更改mixin中的代码:

var BindingExample=React.createClass({            mixins:[BindingMixin],            getInitialState:function(){                return{                    comment:'',                    text:''                }            },            render:function(){                return <div>                <input type="text" placeholder="input" onChange={this.handleChange('text')} />                <textarea onChange={this.handleChange('comment')}></textarea>                <p>{this.state.text}</p>                <p>{this.state.comment}</p>                </div>            }});

这里写图片描述

0 0
原创粉丝点击