javascript - 如何避免渲染方法中的绑定(bind)或内联箭头函数

标签 javascript reactjs arrow-functions function-binding class-fields

我们应该避免在渲染内部绑定(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/

相关文章:

reactjs - React 在无状态组件中添加/删除类 onScroll

Javascript( typescript )Chrome 扩展,函数回调如 promise ?

javascript - 函数的范围问题并转换为箭头函数

JavaScript:获取从页面顶部到任何标签的距离

javascript - 是否有类似附件的垂直盖流 slider ?

javascript - 我的 "div"正在从上到下移动(即距顶部 200 像素的高度)并固定在顶部(起始位置)。但我想固定在底部。我该怎么做?

javascript - React Native Arrow 语法解释

javascript - 刷新页面后 Gif 图像没有动画

node.js - Webpack-dev-server 提供目录列表而不是应用程序页面

javascript - 从已经包含动画的文件渲染和动画化 SVG