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函式中進行傳參。