React组件性能优化最佳实践
React组件性能优化的核心是减少渲染真实DOM节点的频率,减少 Virtual DOM比对的频率。
组件卸载前进行清理操作
在组件中为 window注册的全局事件,以及定时器,在组件卸载前要清理掉,防止组件卸载后继续执行影响应用性能。
需求:开启定时器,然后卸载组件,查看组件中的定时器是否还在运行。
function Test(){
useEffect(()=>{
let timer = setInterval(()=>{
console.log("定时器在执行");
},1000);
return ()=>clearInterval(timer);
},[]);
}
通过纯组件提升组件性能(类组件)
- 什么是纯组件?
纯组件会对组件输入数据进行浅层比较,如果当前输入数据和上次输入数据相同,组件不会重新渲染。
- 什么是浅层比较
比较引用数据类型在内存中的引用地址是否相同,比较基本数据类型的值是否相同
- 如何实现纯组件
类组件继承 PureComponent 类,函数组件使用 memo 方法
- 为什么不直接进行 diff 操作,而是要先进行浅层比较,浅层比较难道没有性能消耗吗
和进行 diff 比较操作相比,浅层比较将消耗更少的性能。diff 操作会重新遍历整棵 virtualDOM 树,而浅层比较只操作当前组件的 state 和 props。
- 需求:在状态对象中存储 name 值为张三,组件挂载完成后将 name 属性的值再次更改为张三,然后分别将 name 传递给纯组件和非纯组件,查看结果。
class App extends Component{
constructor(){
super();
this.state = {
name: "张三"
}
}
updateName(){
setInterval(()=>{
this.setState({name:"张三"});
},1000);
}
componentDidMount(){
this.updateName();
}
render(){
return <>
>
}
}
class ReguarComponent extends Component{
render(){
console.log('ReguarComponent');
return {this.props.name}
}
}
class PureComponentDemo extends PureComponent{
render(){
console.log('PureComponentDemo');
return {this.props.name}
}
}
通过 shouldComponentUpdate 生命周期函数提升组件性能
纯组件只能进行浅层比较,要进行深层比较,使用 shouldComponentUpdate,它用于编写自定义比较逻辑。返回 true 重新渲染组件,返回 false 阻止重新渲染。
函数的第一个参数微 nextProps,第二个参数为 nextState。
需求:在页面中展示员工信息,员工信息包括:姓名、年龄、职位,但是在页面中只想展示姓名和年龄,也就是说只有姓名和年龄发生变化时才有必要重新渲染组件,如果员工的其他信息发生了变化没必要重新渲染组件。
class App extends Component{
constructor(){
super()
this.state ={
person: {
name: "张三",
age: 20,
job: "waiter"
}
}
}
componentDidMount(){
setTimeout(()=>{
this.setState({person:{...this.state.person,job:"chef"}});
},2000);
}
shouldComponentUpdate(nextProps,nextState){
if(nextState.person.name!==this.state.person.name||nextState.person.age!==this.state.person.age){
return true
}
return false
}
render(){
console.log('.....render....');
return {this.state.person.name}{this.state.person.age}
}
}
通过纯组件提升组件性能(函数组件)
将函数组件变为纯组件,将当前 props 和上一次的 props 进行浅层比较,如果相同就阻止组件重新渲染。
需求:父组件维护两个状态,index 和 name,开启定时器让 index 不断发生变化,name 传递给子组件,查看父组件更新子组件是否也更新了。
function App(){
const [name] = useState("张三");
const [index,setIndex] = useState(0);
useEffect(()=>{
setInterval(()=>{
setIndex(prev=>prev+1)
},1000)
},[];
return ({index} )
}
const ShowName = memo(function showName({name}){
return {name}
})
使用 memo方法自定义比较逻辑,用于执行深层比较。比较函数的第一个参数为上一次的 props,比较函数的第二个参数为下一次的 props,比较函数返回 true,不进行渲染,比较函数返回 false,组件重新渲染。
function comparePerson(prevProps,nextProps){
if(prevProps.person.name!==nextProps.person.name||prevProps.person.age!==nextProps.person.age){
return false;
}
return true;
}
const ShowPersonMemo = memo(ShowPerson,comparePerson);
使用组件懒加载
使用组件懒加载可以减少 bundle 文件大小,加快组件呈递速度。
- 路由组件懒加载
import React,{lazy,Suspense} from "react";
import {BrowserRouter,Link,Route,Switch} from "react-router-dom";
const Home =lazy(()=>import("./Home"))
const List = lazy(()=>import("./List"));
function App(){
return (
Home
List
Loading