Javascript React,为每个事件绑定一个新函数的有效性
我的朋友和我在争论。为了充分披露,我是React及其好处的忠实粉丝 在React components中,当将DOM事件附加到元素列表中的每个元素时,传统的模式是Javascript React,为每个事件绑定一个新函数的有效性,javascript,reactjs,dom-events,Javascript,Reactjs,Dom Events,我的朋友和我在争论。为了充分披露,我是React及其好处的忠实粉丝 在React components中,当将DOM事件附加到元素列表中的每个元素时,传统的模式是bind()generic click处理程序,其中包含要作为参数传递给该函数的值。如下文所述: <button onClick={this.onButtonClick.bind(this, buttonIndex)}></button> 我的朋友认为这种做事方式效率极低。这需要创建一个新函数并保存在内存中,以
bind()
generic click处理程序,其中包含要作为参数传递给该函数的值。如下文所述:
<button onClick={this.onButtonClick.bind(this, buttonIndex)}></button>
我的朋友认为这种做事方式效率极低。这需要创建一个新函数并保存在内存中,以处理每个按钮的事件。我同意他的观点,但我觉得如果库不能有效地处理事件及其处理程序,React开发人员不会鼓励这种模式
他用来避免这种情况的模式是使用data-
属性并从DOM元素本身获取值(在本例中为buttonIndex
):
<button data-buttonIndex={buttonIndex} onClick={this.onButtonClick}></button>
再一次,我有偏见,因为我是React的粉丝。但这感觉不对,原因有二:
数据-
属性在我看来非常模糊。它们可以从几个不同的地方设置(HTML、JS、PHP等)。他们也没有暗示任何隐含的目的。“数据”可以在任何地方使用(JS、CSS等)React做了一些特殊的魔法来提高DOM事件的效率吗?如果没有,是否有一种替代模式不使用
data-
属性,并且更明确地说明它的用法?我认为在一般情况下,直接在render
中绑定函数是惯用的方式,因为它们在文档中执行,正如您所指出的,并且根据我们的经验,性能并没有显著降低。但是,在某些情况下,您不希望在每次渲染时重新绑定函数,例如,如果您正在比较shouldComponentUpdate
中的道具(如PureRenderMixin
)。要按照您朋友的建议做一些非常类似的事情,但不使用jQuery查看DOM(我相信这是一种常见的模式),您可以将索引作为道具传递
class Parent extends React.Component {
render() {
return [...some array].map((item, index) => {
return <Child item={item} index={index} />;
});
}
}
class Child extends React.Component {
constructor() {
super();
this.handleClickButton = this.handleClickButton.bind(this);
}
handleClickButton() {
// use this.props.index here
}
render() {
return <button onClick={this.handleClickButton}></button>;
}
}
类父级扩展React.Component{
render(){
返回[…某些数组].map((项,索引)=>{
返回;
});
}
}
子类扩展了React.Component{
构造函数(){
超级();
this.handleClickButton=this.handleClickButton.bind(this);
}
handleClickButton(){
//在此处使用this.props.index
}
render(){
返回;
}
}
注意:当使用ES6类时,您需要在构造函数中手动绑定到
this
,因为您正在访问this.props
。如果使用的是React.createClass
,则不需要这样做 我不确定这是个好主意,但是。。。回忆录
class Foo {
constructor(){
this.getClickHandler = _.memoize(this.getClickHandler);
}
getClickHandler(index){
return (event) => {
doSomething();
};
}
render(){
// ...
<button onClick={this.getClickHandler(index)}>Click me</button>
// ...
}
}
class-Foo{
构造函数(){
this.getClickHandler=\ u0.memoize(this.getClickHandler);
}
getClickHandler(索引){
返回(事件)=>{
doSomething();
};
}
render(){
// ...
点击我
// ...
}
}
这样可以避免创建新函数,避免数据属性,并避免在dom中查找任何内容的性能成本
我不认为我曾经分析过,并发现在渲染中创建函数是一个问题。这绝对是你应该优化的东西,只有当数字告诉你这样做。我很想听到关于这方面的评论。我的看法:“极度”低效?你有多少个按钮<代码>数据-属性“不明确”?他们隐含的目的是。。。传递数据。是的,数据可以在任何地方使用,这对我来说并不是天生的坏,因为你可能想从其他地方使用它<代码>绑定创建一个新函数;无论他们如何处理,React对此无能为力,除非他们编写了自己的绑定。这是内存和易用性之间的折衷。作为一个补充,使用ES6,您现在可以避免讨厌的
绑定
,而是使用箭头函数:this.onButtonClick(buttonIndex)}>
@DaveNewton在表的每一行中都有按钮,表可能有数百行长。您的朋友确定bind
会导致整个函数在内存中重复吗?我认为JavaScript实现人员应该足够聪明,可以将绑定函数存储为对原始函数的引用,以及绑定的this
对象和参数。我想不出函数本身会被复制的原因,但我很想听听你朋友的相反推理。
class Parent extends React.Component {
render() {
return [...some array].map((item, index) => {
return <Child item={item} index={index} />;
});
}
}
class Child extends React.Component {
constructor() {
super();
this.handleClickButton = this.handleClickButton.bind(this);
}
handleClickButton() {
// use this.props.index here
}
render() {
return <button onClick={this.handleClickButton}></button>;
}
}
class Foo {
constructor(){
this.getClickHandler = _.memoize(this.getClickHandler);
}
getClickHandler(index){
return (event) => {
doSomething();
};
}
render(){
// ...
<button onClick={this.getClickHandler(index)}>Click me</button>
// ...
}
}