Javascript 如何避免渲染方法中的绑定或内联箭头函数
我们应该避免渲染内部的方法绑定,因为在重新渲染期间,它将创建新方法,而不是使用旧方法,这将影响性能 所以对于这样的场景:Javascript 如何避免渲染方法中的绑定或内联箭头函数,javascript,reactjs,arrow-functions,function-binding,class-fields,Javascript,Reactjs,Arrow Functions,Function Binding,Class Fields,我们应该避免渲染内部的方法绑定,因为在重新渲染期间,它将创建新方法,而不是使用旧方法,这将影响性能 所以对于这样的场景: <input onChange = { this._handleChange.bind(this) } ...../> 或者我们可以使用: 现在让我们考虑一下我们想传递一些额外的参数,比如在一个简单的ToDo应用程序中,我需要从数组中删除项目的OnCutle,因为我需要在每个OnCutt方法中传递项目索引或todo-Node:< /P> todos.map(el
<input onChange = { this._handleChange.bind(this) } ...../>
或者我们可以使用:
现在让我们考虑一下我们想传递一些额外的参数,比如在一个简单的ToDo应用程序中,我需要从数组中删除项目的OnCutle,因为我需要在每个OnCutt方法中传递项目索引或todo-Node:< /P>
todos.map(el => <div key={el} onClick={this._deleteTodo.bind(this, el)}> {el} </div>)
todos.map(el=>{el})
现在只需假设todo名称是唯一的
根据:
此语法的问题是创建了不同的回调
每次组件渲染时
问题:
如何避免这种在render方法内部绑定的方式,或者有哪些替代方法
请提供任何参考或示例,谢谢。首先:一个简单的解决方案是为map函数内的内容创建一个组件,并将值作为道具传递,当您从子组件调用函数时,可以将值作为道具传递给函数 家长
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>
}
}
deleteTodo=(val)=>{
console.log(val)
}
todos.map(el=>
)
MyComponent
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>
}
}
类MyComponent扩展了React.Component{
deleteTodo=()=>{
this.props.onClick(this.props.val);
}
render(){
返回{this.props.val}
}
}
示例代码段
类父级扩展React.Component{
_deleteTodo=(val)=>{
console.log(val)
}
render(){
var todos=['a','b','c'];
返回(
{todos.map(el=>
)}
)
}
}
类MyComponent扩展了React.Component{
_deleteTodo=()=>{
console.log('here');this.props.onClick(this.props.val);
}
render(){
返回{this.props.val}
}
}
ReactDOM.render(,document.getElementById('app'))代码>
如何避免这种在render方法内部绑定的方式,或者
替代方案
如果您关心重新渲染,那么shouldComponentUpdate
和PureComponent
是您的朋友,他们将帮助您优化渲染
您必须从“父”中提取“子”组件,并始终传递相同的道具,并实现shouldComponentUpdate
或使用PureComponent
。我们想要的是,当我们移除一个子对象时,其他子对象不应该被重新渲染
示例
import React, { Component, PureComponent } from 'react';
import { render } from 'react-dom';
class Product extends PureComponent {
render() {
const { id, name, onDelete } = this.props;
console.log(`<Product id=${id} /> render()`);
return (
<li>
{id} - {name}
<button onClick={() => onDelete(id)}>Delete</button>
</li>
);
}
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
products: [
{ id: 1, name: 'Foo' },
{ id: 2, name: 'Bar' },
],
};
this.handleDelete = this.handleDelete.bind(this);
}
handleDelete(productId) {
this.setState(prevState => ({
products: prevState.products.filter(product => product.id !== productId),
}));
}
render() {
console.log(`<App /> render()`);
return (
<div>
<h1>Products</h1>
<ul>
{
this.state.products.map(product => (
<Product
key={product.id}
onDelete={this.handleDelete}
{...product}
/>
))
}
</ul>
</div>
);
}
}
render(<App />, document.getElementById('root'));
import React,{Component,PureComponent}来自'React';
从'react dom'导入{render};
类产品扩展了PureComponent{
render(){
const{id,name,onDelete}=this.props;
log(`render()`);
返回(
{id}-{name}
onDelete(id)}>Delete
);
}
}
类应用程序扩展组件{
建造师(道具){
超级(道具);
此.state={
产品:[
{id:1,名称:'Foo'},
{id:2,名称:'Bar'},
],
};
this.handleDelete=this.handleDelete.bind(this);
}
handleDelete(产品ID){
this.setState(prevState=>({
产品:prevState.products.filter(产品=>product.id!==productId),
}));
}
render(){
console.log(`
预期行为
- François Zaninoto的
。这个答案肯定是详尽无遗的,但我要说的是,与过度的重新渲染作斗争而不是仅仅重新创建微小的回调会给您带来更多的性能改进。这通常是通过在子组件中实现适当的shouldComponentUpdate
来实现的
即使道具完全相同,以下代码仍将重新呈现子级,除非它们在自己的shouldComponentUpdate
中阻止它(它们可能从PureComponent
继承它):
鼓励使用数据属性并从evt.target.dataset
中访问它们:
_deleteTodo = (evt) => {
const elementToDelete = evt.target.dataset.el;
this.setState(prevState => ({
todos: prevState.todos.filter(el => el !== elementToDelete)
}))
}
// and from render:
todos.map(
el => <div key={el} data-el={el} onClick={this._deleteTodo}> {el} </div>
)
\u deleteTodo=(evt)=>{
const elementToDelete=evt.target.dataset.el;
this.setState(prevState=>({
todos:prevState.todos.filter(el=>el!==elementToDelete)
}))
}
//从渲染:
todos.map(
el=>{el}
)
此外,这只有在出现性能问题时才有意义:
可以在渲染方法中使用箭头函数吗?
一般来说,是的,这是可以的,而且这通常是最简单的方法
将参数传递给回调函数
如果您确实存在性能问题,请务必进行优化
是的,我们可以做到这一点,但有了它,我们需要创建单独的组件并放置父子关系,我认为这将没有那么大的可伸缩性,因为在大型应用程序中,我们通常在多个位置进行这种绑定。我也曾对此进行过斗争,我的结论是,如果这种函数的重新创建会减慢应用程序的开发速度own(我想,如果有足够大的数据集进行大量重新渲染,可能会发生这种情况),对于这些组件,您应该遵循此方法。否则,这对性能来说并不是一个真正的问题,因此可以安全地忽略。是的,但是如何避免您想要的内容和可伸缩性不应该是本文中的问题。在创建类属性时,您使用deleteTodo
,但是当您进行refe请使用\u deleteTodo
。这是一个错误还是下划线在这里有什么特殊用途?@akshaykishore,在这种情况下,您可以使用第三种方法,而不是将索引传递给onclick谢谢您的建议,但我认为使用unique key可以解决这个问题。我们需要的是在删除子项时使用第三种方法,其他c孩子们不应该被重新渲染
shouldComponentUpdate(nextProps) {
return this.props.array !== nextProps.array;
}
_deleteTodo = (evt) => {
const elementToDelete = evt.target.dataset.el;
this.setState(prevState => ({
todos: prevState.todos.filter(el => el !== elementToDelete)
}))
}
// and from render:
todos.map(
el => <div key={el} data-el={el} onClick={this._deleteTodo}> {el} </div>
)