Javascript中的this
值总是能让很多初学者感到困惑,总的来说this
值就是指向调用函数的那个对象。但是call
, apply
, bind
方法和ES6中箭头函数让this
值还是要具体情况具体分析,不过这块知识点并不是很难,对应的博客也很多,花点时间就能掌握。接下来主要介绍React中this
值绑定和事件函数传参。
React中this值绑定
React中也有this
值的绑定问题,接下来将介绍五种绑定模式。
使用React.createClass
如果你使用React.createClass
来创建组件,那么React会自动把函数中的this
值指向组件实例。
React.createClass({
getInitialState: function() {
return {
text: 'text'
};
},
handleChange: function(event) {
this.setState({
text: event.target.value
});
},
render: function() {
return (
<div>
Type something:
<input onChange={this.handleChange} value={this.state.text} />
</div>
)
}
})
复制代码
上面的例子中input
的onChange
处理函数直接指向了handleChange
方法,在使用React.createClass
方法创建组件中这是可行的。
要注意的是,React.createClass
在React 16.0.0 版本中就从核心包移除出去了,要从 create-react-class 中获取。
同时官方是推荐使用 ES6 类语法来进行组件的定义,所以这个this
值的绑定方法是不推荐的。
在Render函数中绑定
通常我们都是使用 ES6 类语法来进行组件的定义,此时 React 并不会自动绑定 this
值。一种解决方法是在render
函数中进行 this
值绑定:
onChange={this.handleChange.bind(this)}
复制代码
这种方法简明清晰,但是对性能会有些影响,因为每次渲染时都会使用bind
方法创建一个新函数。
在Render函数中使用箭头函数
这个方法和使用bind
函数有些类似,你可以在render
中使用箭头函数来保证this
值是指向组件实例的。
onChange={e => this.handleChange(e)}
复制代码
同样的这种方法也是对性能有影响的,箭头函数每次渲染时都要重新创建。
在构造函数中进行绑定
在构造函数中进行this
值的绑定应该是大多数人在使用的,它避免了每次渲染时都要重新创建事件方法。
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
复制代码
但是有时方法比较多的情况下,构造函数中充满了绑定方法,显得很冗长。
定义类属性的时候使用箭头函数
这种语法还在提案阶段,你可以使用transform-class-properties 或者 Babel 中的 stage-2 来完成转码。
handleChange = () => {
// call this function from render
// and this.whatever in here works fine.
}
复制代码
箭头函数的this
中是指向外层作用域中this
值的。所以这个方法中this
值总是指向组件实例的,同时它也不会也上边提到的性能问题。所以说推荐使用这种方法来处理this
的绑定。
事件传参
讲完了this
值的绑定,接下来快速讨论下事件函数的传参问题。
简单快速的方法
- 在使用
bind
函数的时候进行传参。
<th value={column} onClick={this.handleSort.bind(null, column)}>{column}</th>
复制代码
这边提一下,event
对象也会在你的传输后面默认传入。
- 箭头函数传参
<th value={column} onClick={(event) => this.handleSort(column, event)}>{column}</th>
复制代码
从DOM元素属性中获取
handleSort(event) {
const value = event.target.getAttribute('value')
}
<th value={column} onClick={this.handleSort}>{column}</th>
复制代码
抽离出一个子组件
抽离出一个子组件,这样可以避免渲染时一直重新创建事件函数导致的性能问题。
首先主模块:
{this.props.defaultColumns.map((column) => (
<TableHeader
value={column}
onHeaderClick={this.handleSort}
/>
))}
复制代码
子组件:
class TableHeader extends Component {
handleClick = () => {
this.props.onHeaderClick(this.props.value);
}
render() {
return (
<th onClick={this.handleClick}>
{this.props.column}
</th>
);
}
}
复制代码
子组件继承PureComponent
只会在props
发生改变时才会重新渲染(自动浅比较)。
这个最佳实践在eslint-plugin-react
中也是有的,所以推荐写代码时开启Eslint。
总结
this
值的绑定首先推荐使用类属性箭头函数的方式来处理,其次是在构造函数中进行绑定。- 事件函数传参可以抽离一个子组件或者从DOM属性获取来完成。不考虑性能可能在render函数中进行传参。