在以前的文章中,已經說明如何避免在react jsx中使用箭頭函數和bind(https://medium.freecodecamp.o... 可是沒有提供一個清晰的demo展現爲何要這樣作。html
如今來一些例子吧。react
在這個例子中,咱們經過使用一個箭頭函數(=>)來bind用戶ID到每一個刪除按鈕中。git
## index.js import React from 'react'; import { render } from 'react-dom'; import User from './User'; class App extends React.Component { constructor(props) { super(props); this.state = { users: [ { id: 1, name: 'Cory' }, { id: 2, name: 'Meg' }, { id: 3, name: 'Bob' } ] }; } deleteUser = id => { this.setState(prevState => { return { users: prevState.users.filter( user => user.id !== id) } }) } render() { return ( <div> <h1>Users</h1> <ul> { this.state.users.map( user => { return <User key={user.id} name={user.name} onDeleteClick={() => this.deleteUser(user.id)} /> }) } </ul> </div> ); } } export default App; render(<App />, document.getElementById('root'));
在onDeleteClick={() => this.deleteUser(user.id)}
這一行中,咱們使用一個箭頭函數來傳遞value到deleteUser 函數中。這就是問題所在了。程序員
## User.js import React from 'react'; // Note how the debugger below gets hit when *any* delete // button is clicked. Why? Because the parent component // uses an arrow function, which means this component // class User extends React.PureComponent { render() { const {name, onDeleteClick } = this.props console.log(`${name} just rendered`); return ( <li> <input type="button" value="Delete" onClick={onDeleteClick} /> {name} </li> ); } } export default User;
看一看User.js文件。每當我登陸的時候控制檯都會打印出渲染執行時的console結果。我已經定義User
爲PureComponent。因此只有當props或者state修改時纔會從新渲染User
。可是當你點擊刪除的時候,發現render在全部User實例中觸發了。github
怎麼會這個樣子?由於()=>this.deleteUser(user.id)
每執行一次就會生成一個新的函數,固然bind也是這樣乾的,因此在PureComponent的shallowCompare中認爲onDeleteClick的值已經被修改,因此觸發了從新渲染。看吧,使用箭頭函數和bind會形成性能浪費,做爲一個節約的程序員應該避免如此。api
請看下面的代碼閉包
import React from 'react'; import { render } from 'react-dom'; import User from './User'; class App extends React.Component { constructor(props) { super(props); this.state = { users: [ { id: 1, name: 'Cory' }, { id: 2, name: 'Meg' }, { id: 3, name: 'Bob'} ], }; } deleteUser = id => { this.setState(prevState => { return { users: prevState.users.filter(user => user.id !== id) }; }); }; renderUser = user => { return <User key={user.id} user={user} onClick={this.deleteUser} />; } render() { return ( <div> <h1>Users</h1> <ul> {this.state.users.map(this.renderUser)} </ul> </div> ); } } render(<App />, document.getElementById('root'));
上面的例子就沒有箭頭函數了。這裏面使用了閉包的概念,把user傳遞下去了。dom