对于大多数前端开发来讲,JavaScript 的 this 关键字会形成诸多困扰,因为 JavaScript 代码中的 this 指向并不清晰。在写react应用时,也会也到不少做用域绑定引发的问题,React组件ES6的写法,不会将方法内部的做用域自动绑定到组件的实例上。javascript
下面展现一段问题代码前端
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而报错。java
咱们都知道常规改变函数做用域的无非3种(Fiontion.prototype.bind call apply 三兄弟),下面讲解一下在es6中bind做用域的几种方式。react
使用Function.prototype.bind()git
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> } }
ES7函数绑定语法
在 ES7 中,有一个关于 bind 语法 的提议,提议将 :: 做为一个新的绑定操做符, 并且已经收录在stage-0提案中,实际上::是Function.propotype.bind()的一种语法糖。 幸运的是,Babel已经提供了对这个新语法的支持。es6
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> } }
在构造函数中bind thisgithub
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> } }
使用箭头函数app
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> } }
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提供了不少使用的装饰器。ui
某些场景下,咱们须要传递额外的参数,好比列表中删除操做,须要传id。经常使用的方案是方案1和方案4
// Function.prototype.bind() <Item onClick={this.doDelete.bind(this, id)}>删除</Item> // 箭头函数 <Item onClick={(...args)=>{ this.doDelete(id, ...args) }}>删除</Item>