react系列-bind this

题目

关于大多数前端开辟来讲,JavaScript 的 this 关键字会形成诸多搅扰,由于 JavaScript 代码中的 this 指向并不清楚。在写react应用时,也会也到许多作用域绑定引发的题目,React组件ES6的写法,不会将要领内部的作用域自动绑定到组件的实例上。

下面展现一段题目代码

class Search extends Component {
    static propTypes = {
        onSearch: React.PropTypes.func.isRequired
    }
    onSearch() {
        console.log('表单值:', this.field.getValues());
        this.props.onSearch(this.field.getValues());
    }
    render(){
        const {init} = this.field;
        return <div>
            <Form direction="hoz" labelAlign="left">
                    <FormItem label="loginID:">
                        <Input placeholder="请输入loginID" {...init('loginID')}/>
                    </FormItem>
                    <Button type="primary" onClick={this.onSearch}>搜刮</Button>
            </Form>
        </div>
    }
}

假如你真的尝试这么做了, 你会发如今onSearch中,由于this指向的是全局对象window而报错。

解决办法

我们都晓得通例转变函数作用域的不过3种(Fiontion.prototype.bind call apply 三兄弟),下面解说一下在es6中bind作用域的几种体式格局。

  1. 运用Function.prototype.bind()

    class Search extends Component {
        render(){
            return <div>
                <Form direction="hoz" labelAlign="left">
                        <FormItem label="loginID:">
                            <Input placeholder="请输入loginID" {...init('loginID')}/>
                        </FormItem>
                        <Button type="primary" onClick={this.onSearch.bind(this)}>搜刮</Button>
                </Form>
            </div>
        }
    }
  2. ES7函数绑定语法
    在 ES7 中,有一个关于 bind 语法 的发起,发起将 :: 作为一个新的绑定操纵符, 而且已收录在stage-0提案中,实际上::是Function.propotype.bind()的一种语法糖。 荣幸的是,Babel已供应了对这个新语法的支撑。

    class Search extends Component {
        render(){
            return <div>
                <Form direction="hoz" labelAlign="left">
                        <FormItem label="loginID:">
                            <Input placeholder="请输入loginID" {...init('loginID')}/>
                        </FormItem>
                        <Button type="primary" onClick={::this.onSearch}>搜刮</Button>
                </Form>
            </div>
        }
    }
  3. 在组织函数中bind this

        class Search extends Component {
        constructor(props) {
            super(props);
            this.onSearch = this.onSearch.bind(this)
        }
        render(){
            return <div>
                <Form direction="hoz" labelAlign="left">
                        <FormItem label="loginID:">
                            <Input placeholder="请输入loginID" {...init('loginID')}/>
                        </FormItem>
                        <Button type="primary" onClick={this.onSearch}>搜刮</Button>
                </Form>
            </div>
        }
    }
  4. 运用箭头函数

    class Search extends Component {
        render(){
            return <div>
                <Form direction="hoz" labelAlign="left">
                        <FormItem label="loginID:">
                            <Input placeholder="请输入loginID" {...init('loginID')}/>
                        </FormItem>
                        <Button type="primary" onClick={(...args)=>{
                            this.onSearch( ...args)
                        }}>搜刮</Button>
                </Form>
            </div>
        }
    }
  5. core-decorators.js
    core-decorators.js为开辟者供应了一些有用的 decorator,个中完成的autobind润饰器能使得要领中的this对象绑定到原始对象

class Search extends Component {
    @autobind
    onSearch() {
        console.log('表单值:', this.field.getValues());
        this.props.onSearch(this.field.getValues());
    }
    render(){
        const {init} = this.field;
        return <div>
            <Form direction="hoz" labelAlign="left">
                    <FormItem label="loginID:">
                        <Input placeholder="请输入loginID" {...init('loginID')}/>
                    </FormItem>
                    <Button type="primary" onClick={this.onSearch}>搜刮</Button>
            </Form>
        </div>
    }
}

总结

比较

这里我们议论下以上几种将this绑定到react组件计划的瑕玷,长处本身体味吧。
计划1和计划2,瑕玷也很严重,这类体式格局破坏了组件的pure render,每次组件render时,子组件Button的onClick值都是从新赋值所得,会致使Button做一次无谓的render。而且函数绑定语法::属于es7草案中的特征,还没有归入es规范。运用须要郑重。
计划3和计划4会增添代码量
计划5须要引入第三方库,不过core-decorators.js供应了许多运用的装潢器。

场景

某些场景下,我们须要通报分外的参数,比方列表中删除操纵,须要传id。经常使用的计划是计划1和计划4

// Function.prototype.bind()
<Item onClick={this.doDelete.bind(this, id)}>删除</Item>
// 箭头函数
<Item onClick={(...args)=>{
    this.doDelete(id, ...args)
}}>删除</Item>
    原文作者:amibug
    原文地址: https://segmentfault.com/a/1190000007207233
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞