问题
对于大多数前端开发来说,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>
}
}