做asp.net网站参考文献,福州网站建设外包,婚庆策划公司装修,购物网站建设市场目录 1#xff0c;什么是 PureComponent2#xff0c;什么是 memo3#xff0c;举例3.2#xff0c;优化13.1#xff0c;优化2-函数位置 4#xff0c;注意点4.1#xff0c;为了提升效率#xff0c;应该尽量使用 PureComponent4.2#xff0c;不要直接改变之前的状态#… 目录 1什么是 PureComponent2什么是 memo3举例3.2优化13.1优化2-函数位置 4注意点4.1为了提升效率应该尽量使用 PureComponent4.2不要直接改变之前的状态而是覆盖4.3为什么不进行深比较 1什么是 PureComponent
纯组件为了避免不必要的渲染运行 render来提升效率。
优化思路如果一个组件的状态和属性都没有变化那就不用重新渲染。
具体实现当某个组件 extends PureComponent 时则该组件的 shouldComponentUpdate 中会对新旧属性和状态进行浅比较如果都相等则不会重新渲染return false。
// 原理大致如下
import React, { Component } from react;export default class Task extends Component {shouldComponentUpdate(nextProps, nextState) {if (isEqual(this.props, nextProps) isEqual(this.state, nextState)) {return false;}return true;}render() {}
}const isEqual (obj1, obj2) {for (const key in obj1) {if (obj1[key] ! obj2[key]) {return false}}return true
}效果等于
import React, { PureComponent } from react;export default class Task extends PureComponent {render() {}
}2什么是 memo
React.memo 是一个HOC相当于给函数组件套了一个 PureComponent让函数组件也能进行优化。
// 大致原理
import React, { PureComponent } from react;function memo(funcComp) {return class Memo extends PureComponent {render() {return {funcComp(this.props)}/}};
}3举例
一个展示列表的组件逻辑很简单结构如下
-- TaskContainer-- TaskList-- Task-- TaskAdd一个输入框可以新增列表项 TaskContainerconsole.log(container render);
import React, { Component } from react;
import TaskAdd from ./TaskAdd;
import TaskList from ./TaskList;export default class TaskContainer extends Component {state {list: Array.from(new Array(10)).map((item, index) 任务${index}),};render() {console.log(container render);return (divTaskAddchangeList{(newTask) {this.setState({list: [...this.state.list, newTask],});}}/TaskAddTaskList list{this.state.list}/TaskList/div);}
}TaskListconsole.log(list render);
import React, { Component } from react;
import Task from ./Task;export default class TaskList extends Component {render() {console.log(list render);return (div{(this.props.list || []).map((m) (Task name{m} key{m}/Task))}/div);}
}TaskAddconsole.log(add render);
import React, { Component } from react;export default class TaskAdd extends Component {state {taskName: ,};render() {console.log(add render);return (divinputvalue{this.state.taskName}onChange{(e) {this.setState({ taskName: e.target.value });}}/inputbutton onClick{() this.props.changeList(this.state.taskName)}添加任务/button/div);}
}Taskconsole.log(task render);
import React, { Component } from react;export default class Task extends Component {render() {console.log(task render);return div{this.props.name}/div;}
}使用
import React, { Component, Component } from react;
import TaskContainer from ./components/Pure/TaskContainer;export default class App extends Component {render() {return TaskContainer/TaskContainer;}
}初次渲染时打印结果
container render
add render
list render
10次 task render添加一个列表项时打印结果
container render
add render
list render
11次 task render3.2优化1
当添加一个列表项时已经被渲染的10个 task 不应该再次渲染因为它们自身没有发生任何变化。只应该渲染新增的那一个即可。
此时就可以用到 PureComponent
export default class Task extends Component {}
// 替换为
export default class Task extends PureComponent {}这时再添加一个列表项时在打印结果可以看到 Task 只渲染了一次新增的。
container render
add render
list render
task render3.1优化2-函数位置
注意到新增列表时TaskAdd 组件在点击按钮后不应该再次渲染不应该打印 add render因为它的状态和属性也没有发生变化。
也做下替换
export default class TaskAdd extends Component {}
// 替换为
export default class TaskAdd extends PureComponent {}发现结果并没有发生变化add render 依旧会打印。
这时因为在 TaskContainer 中给组件 TaskAdd 传递的属性 changeList 是直接写在组件上的。这样每次执行 TaskContainer.render() 时都算作一个新的属性所以 TaskAdd extends PureComponent 没有生效。
做以下替换即可
export default class TaskContainer extends Component {render() {return (divTaskAddchangeList{(newTask) {this.setState({list: [...this.state.list, newTask],});}}/TaskAdd/div);}
}// 替换为
export default class TaskContainer extends Component {changeList (newTask) {this.setState({list: [...this.state.list, newTask],});};render() {return (divTaskAdd changeList{this.changeList}/TaskAdd/div);}
}4注意点
4.1为了提升效率应该尽量使用 PureComponent
4.2不要直接改变之前的状态而是覆盖 旧的状态应该是不可变的immutable只能通过创建新状态来覆盖之前的状态。 举例当使用 PureComponent 时下面的代码不会更新数据。因为进行的是浅比较此时数组地址相同。
this.state.task.push(xxx)
this.setState({task: this.state.task
})换成下面的方式就可以了产生了新数组。
this.setState({task: [...this.state.task, xxx]
})
// 或
this.setState({task: this.state.task.concat(xxx)
})如果是对象的话产生了新对象。
this.setState({obj: {...this.state.obj,b: xxx}
})
// 或
this.setState({obj: Object.assign({}, this.state.obj, {b: xxx})
})4.3为什么不进行深比较
因为本来就是为了提升效率减少 render 执行次数。深比较会比较费时得不偿失。 以上。