小编典典

如何避免render方法中的绑定或内联箭头功能

javascript

我们应该避免在render内部绑定方法,因为在重新渲染期间它将创建新方法而不是使用旧方法,这会影响性能。

所以对于这样的场景:

<input onChange = { this._handleChange.bind(this) } ...../>

我们可以_handleChange在构造函数中绑定方法:

this._handleChange = this._handleChange.bind(this);

或者我们可以使用属性初始化器语法

_handleChange = () => {....}

现在让我们考虑一下要传递一些额外参数的情况,比如说在一个简单的todo应用中,项目的onclick我需要从数组中删除该项目,为此我需要在每个项目中传递项目索引或todo名称onClick方法:

todos.map(el => <div key={el} onClick={this._deleteTodo.bind(this, el)}> {el} </div>)

现在,仅假定待办事项名称是唯一的。

根据 DOC

这种语法的问题在于,每次渲染组件时都会创建一个不同的回调。

题:

如何避免在render方法中使用这种绑定方式,或者有什么替代方法?

请提供任何参考或示例,谢谢。


阅读 341

收藏
2020-04-25

共1个答案

小编典典

首先: 一个简单的解决方案是为map函数内部的内容创建一个组件并将值作为prop传递,当您从子组件中调用函数时,可以将值传递给props传递的函数。

Parent

deleteTodo = (val) => {
    console.log(val)
}
todos.map(el => 
    <MyComponent val={el} onClick={this.deleteTodo}/>

)

MyComponent

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>

编辑:

第二: 另一种方法是使用备忘录并返回一个函数

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>)

PS但是,这不是最佳解决方案,仍然会导致创建多个功能,但与初始情况相比仍是一个改进。

第三: 不过,更合适的解决方案是attribute在最上面的div中添加an 并从eventlike 获得值

_deleteTodo = (e) => {
     console.log(e.currentTarget.getAttribute('data-value'));

 }

 todos.map(el => <div key={el} data-value={el} onClick={this._deleteTodo}> {el} </div>)

但是,在这种情况下,使用toString方法将属性转换为字符串,因此and对象将被转换为[ObjectObject]and和array,["1" ,"2", "3"]"1, 2, 3"

2020-04-25