React 基础巩固(二十三)——React 性能优化 SCU
React 更新机制
-
React 的渲染流程
- JSX -> 虚拟 DOM -> 真实 DOM
-
React 的更新流程
-
props/state 改变
->render函数重新执行
->产生新的DOM树
->新旧DOM树进行diff
->计算出差异进行更新
->更新到真实的DOM
-
-
React 在 props 或 state 发生改变时,会调用 React 的 render 方法,会创建一颗不同的树
-
React 需要基于这两颗不同的树之间的差别来判断如何有效的更新 UI
- 如果一颗树参考另外一颗树进行完全比较更新,那么即使时最先进的算法,该算法的复杂度为 O(n^2),其中 n 是树中元素的数量;
- 如果在 React 中使用了该算法,那么展示 1000 个元素所需要执行的计算量将在 10 亿的量级范围;
- 开销过于昂贵,更新性能非常低效;
-
于是,React 对这个算法进行了优化,将其优化成了 O(n)
- 同层节点之间相互比较,不会跨节点比较
- 不同类型的节点,产生不同的树结构
- 开发中,可以通过 key 来指定哪些节点在不同的渲染下保持稳定
-
keys 的优化
- 遍历列表时,会提示一个警告,提示我们加入一个 key 属性
- 当子元素拥有 key 时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素
- 例如将 key 为 333 的元素插入到最前面的位置时,key 为 111,222 的元素,仅仅需要进行位移即可,不需要任何修改
-
key 的注意事项
- key 应该是唯一的
- key 不要使用随机数(随机数在下一次 render 时,会重新生成一个数字)
- 使用 index 作为 key,对性能是没有优化的
-
render 函数被调用
- 为了避免不必要的 render,提高性能,调用 render 应该有一个前提:依赖的数据(state、props)发生改变时,再调用 render 方法
-
利用
shouldComponentUpdate
优化 render 调用
// 针对值发生变化的组件
shouldComponentUpdate(nextProps, newState){
// 对比 state中的值是否有改变
if (this.state.message !== newState.message || this.state.counter !== newState.counter){
return true
}
return false
}
// 针对其中的子组件
shouldComponentUpdate(nextProps, newState){
// 1.对比 state中的值是否有改变
if (this.state.message !== newState.message || this.state.counter !== newState.counter){
return true
}
// 2.检测接收的props是否有改变
if (this.props.message !== newProps.message){
return true
}
return false
}
- 如果参数过多,SCU 的方式则过于繁琐,所以通常采用以下方式实现
针对类组件:采用PureComponent 实现优化
import React, { PureComponent } from "react";
export class App extends PureComponent {
// ...
}
PureComponent中变更数组数据的实际应用:文章来源:https://www.toymoban.com/news/detail-554828.html
import React, { PureComponent } from "react";
export class App extends PureComponent {
constructor() {
super();
this.state = {
books: [
{ name: "book1", price: 199, count: 1 },
{ name: "book2", price: 299, count: 1 },
{ name: "book3", price: 399, count: 2 },
{ name: "book4", price: 499, count: 3 },
{ name: "book5", price: 599, count: 1 },
],
};
}
addNewBook() {
const newBook = {
name: "book6",
price: 55,
count: 1,
};
// 错误写法:
// 直接修改原有的state,重新设置一遍
// this.state.books.push(newBook);
// this.setState({
// books: this.state.books,
// });
// 正确写法:
// 拷贝一份,在新的数组中更新,设置新的books,而不是直接修改state
const books = [...this.state.books];
books.push(newBook);
this.setState({ books });
}
addBookCount(index) {
console.log(index);
const books = [...this.state.books];
books[index].count++;
this.setState({ books });
}
render() {
const { books } = this.state;
return (
<div>
<h2>books list</h2>
<ul>
{books.map((item, index) => {
return (
<li key={index}>
<span>
name: {item.name} - price: {item.price} - count: {item.count}
</span>
<button onClick={(e) => this.addBookCount(index)}>+1</button>
</li>
);
})}
</ul>
<button onClick={(e) => this.addNewBook()}>添加新书籍</button>
</div>
);
}
}
export default App;
针对函数式组件:采用 memo 实现优化文章来源地址https://www.toymoban.com/news/detail-554828.html
import { memo } from "react";
const Profile = memo(function (props) {
console.log("profile render");
return <h2>Profile: {props.message}</h2>;
});
export default Profile;
到了这里,关于【前端知识】React 基础巩固(二十三)——React 性能优化 SCU相关的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!