在以前的文章中,已经说明如何避免在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