前言
由於JS的靈活性,我們在React中其實有很多種繫結事件的方式,然而,其實有許多我們常見的事件繫結,其實並不是高效的。所以本文想給大家介紹一下React繫結事件的正確姿勢。
常見兩種種錯誤繫結事件
class ErrorExample1 extends Component {
balabala(e) {console.log(e)}
render() {
const { text } = this.state;
return (
<Wrapper>
{text}
<Balabala onClick={(e) => this.balabala(e)}></Balabala>
</Wrapper>
)
}
}
class ErrorExample2 extends Component {
balabala(e) {console.log(e)}
render() {
const { text } = this.state;
return (
<Wrapper>
{text}
<Balabala onClick={this.balabala.bind(this)}></Balabala>
</Wrapper>
)
}
}
這是兩種最常見的React繫結事件程式碼,但它為什麼是錯誤的?
每當你的text發生變化,就會rerender,只要元件重新render,那就會重新建立新的事件函式,進而繫結事件,這個過程的開銷就是極大極大的浪費。相當於,每次rerender都會建立一次事件函式。
這據說是 Best Practice
class Balabala extends Component {
constructor(p) {
suprt(p);
this.balabala = this.balabala.bind(this);
}
render() {
const { text } = this.state;
return (
<Wrapper>
{text}
<Balabala onClick={this.balabala}></Balabala>
</Wrapper>
)
}
}
然而我更喜歡的姿勢
class Balabala extends Component {
constructor(p) {
suprt(p);
}
醒來記得想我 = (e) => {
alert(`想你了`);
}
render() {
const { text } = this.state;
return (
<Wrapper>
{text}
<Balabala onClick={this.醒來記得想我}></Balabala>
</Wrapper>
)
}
}
利用箭頭函式,幫我們bind this。避免了在建構函式裡生命一堆的變數。減少鍵盤的敲擊,延長生命。
當然,還有人會問,這樣的寫法如何傳參呢?以前別人會這樣寫
class 渣男 extends Component {
constructor(p) {
suprt(p);
}
醒來記得想我 = (e, text) => {
alert(text); // alert 滾吧,渣男
}
render() {
const { text } = this.state;
return (
<Wrapper>
{text}
<Balabala onClick={this.醒來記得想我.bind(e, `滾吧,渣男`)}></Balabala>
</Wrapper>
)
}
}
但是其實,我們可以這樣傳參,更加簡潔明瞭
class 渣男 extends Component {
constructor(p) {
suprt(p);
}
醒來記得想我 = (text) => (event) => {
alert(text); // 你渣我也喜歡,因為是你
}
render() {
const { text } = this.state;
return (
<Wrapper>
{text}
<Balabala onClick={this.醒來記得想我( `你渣我也喜歡,因為是你`)}></Balabala>
</Wrapper>
)
}
}
動態繫結
基於這個我們還可以針對同一事件修改多個input值,進行事件優化
class ChangeMyName extends Component {
修改渣男名稱 = name => {
if (!this.handlers[name]) {
this.handlers[name] = event => {
this.setState({ [name]: event.target.value });
};
}
return this.handlers[name];
}
render() {
return (
<>
<input onChange={this.修改渣男名稱(`男神1號`)}/>
<input onChange={this.修改渣男名稱(`渣男2號`)}/>
</>
)
}
}
旁門左道,邪教!(個人不喜歡而已)
import autoBind from `react-autobind`;
class Balabala extends Component {
constructor() {
autoBind(this);
}
醒來記得想我 (e) {
alert(`想你了`);
}
render() {
const { text } = this.state;
return (
<Wrapper>
{text}
<Balabala onClick={this.醒來記得想我}></Balabala>
</Wrapper>
)
}
}
import { BindAll } from `lodash-decorators`;
@BindAll()
class Bbb extends Component {}
// 這種寫法等同於 bind
class Bbb extends Component {
balabala(){}
render() {
const { text } = this.state;
return (
<Wrapper>
{text}
<Balabala onClick={::this.balabala}></Balabala>
</Wrapper>
)
}
}
基本都大同小異吧,就不過多介紹了。看到這裡,你也知道到底應該如何繫結事件了。
個人網站:http://meckodo.com