我们应该避免在渲染内部绑定(bind)方法,因为在重新渲染期间它将创建新方法而不是使用旧方法,这会影响性能。
对于这样的场景:
<input onChange = { this._handleChange.bind(this) } ...../>
我们可以在构造函数中绑定(bind)_handleChange
方法:
this._handleChange = this._handleChange.bind(this);
或者我们可以使用property initializer syntax :
_handleChange = () => {....}
现在让我们考虑一下我们想要传递一些额外参数的情况,比如说在一个简单的待办事项应用程序中,单击项目时我需要从数组中删除该项目,因为我需要传递项目索引或待办事项每个 onClick 方法中的名称:
todos.map(el => <div key={el} onClick={this._deleteTodo.bind(this, el)}> {el} </div>)
现在假设待办事项名称是唯一的。
根据 DOC :
The problem with this syntax is that a different callback is created each time the component renders.
问题:
如何避免这种在渲染方法内绑定(bind)的方式或者有什么替代方法?
请提供任何引用或示例,谢谢。
最佳答案
第一:一个简单的解决方案是为 map 函数内的内容创建一个组件,并将值作为 props 传递,当您从子组件调用该函数时,您可以将值传递给作为 props 传递的函数。
父级
deleteTodo = (val) => {
console.log(val)
}
todos.map(el =>
<MyComponent val={el} onClick={this.deleteTodo}/>
)
我的组件
class MyComponent extends React.Component {
deleteTodo = () => {
this.props.onClick(this.props.val);
}
render() {
return <div onClick={this.deleteTodo}> {this.props.val} </div>
}
}
示例片段
class Parent extends React.Component {
_deleteTodo = (val) => {
console.log(val)
}
render() {
var todos = ['a', 'b', 'c'];
return (
<div>{todos.map(el =>
<MyComponent key={el} val={el} onClick={this._deleteTodo}/>
)}</div>
)
}
}
class MyComponent extends React.Component {
_deleteTodo = () => {
console.log('here'); this.props.onClick(this.props.val);
}
render() {
return <div onClick={this._deleteTodo}> {this.props.val} </div>
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
编辑:
第二:另一种方法是使用 memoize 并返回一个函数
constructor() {
super();
this._deleteTodoListener = _.memoize(
this._deleteTodo, (element) => {
return element.hashCode();
}
)
}
_deleteTodo = (element) => {
//delete handling here
}
并像这样使用它
todos.map(el => <div key={el} onClick={this._deleteTodoListener(el)}> {el} </div>)
P.S. However this is not a best solution and will still result in multiple functions being created but is still an improvement over the initial case.
第三: 然而,更合适的解决方案是将 attribute
添加到最上面的 div 并从 event
获取值,例如
_deleteTodo = (e) => {
console.log(e.currentTarget.getAttribute('data-value'));
}
todos.map(el => <div key={el} data-value={el} onClick={this._deleteTodo}> {el} </div>)
但是,在这种情况下,使用 toString 方法将属性转换为字符串,因此对象将转换为 [Object Object]
和数组,如 ["1", "2 ", "3"]
为 "1, 2, 3"
关于javascript - 如何避免渲染方法中的绑定(bind)或内联箭头函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45053622/