美文网首页
react系列-bind this

react系列-bind this

作者: 小豆soybean | 来源:发表于2018-08-08 20:06 被阅读0次

原文链接:https://segmentfault.com/a/1190000007207233
对于大多数前端开发来说,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>

相关文章

  • react系列-bind this

    原文链接:https://segmentfault.com/a/1190000007207233对于大多数前端开发...

  • React系列bind this

    在实际开发中遇到事件不执行的情况,一直不理解bind函数,正好理理,代码如下 this.handleClick中t...

  • React .bind()

    当使用es5时,是不需要用.bind()的。当使用es5 时,React会自动帮助我们给每一个function绑定...

  • react bind

    前置知识 原因:在temp作为中间量转换的时候丢失了this的指向 在react中 bind的原理同上方一致,在j...

  • react性能优化 不要再component的props中使用箭头函数或者bind,因为每次使用箭头函数和bind...

  • React bind this的五种方式介绍

    react中避免不了经常需要对this进行操作,而事件默认react是不被bind到当前react实例上的,需要手...

  • React (TypeScript)

    React with TypeScript 系列(一) --概述 React with TypeScript 系列...

  • react的bind

    问题描述 今天重构项目的路由代码,遇到了一个问题,在app.js 的文件中,我使用react-router路由如下...

  • react的bind(this)

    在调用this.setState()的时候出现了this为undefined的情况,如何处理。(四种写法,其中一种...

  • 面试官问:能否模拟实现JS的bind方法

    前言 用过React的同学都知道,经常会使用bind来绑定this。 那么面试官可能会问是否想过bind到底做了什...

网友评论

      本文标题:react系列-bind this

      本文链接:https://www.haomeiwen.com/subject/dgzxbftx.html