React组件性能优化最佳实践React组件性能优化的核心是降低渲染真实DOM节点的频率,降低VirtualDOM比较的频率。如果子组件的数据没有变化,则子组件不会被渲染。组件卸载前的清理操作下面的代码会在组件销毁时创建一个间隔定时器,并清除该定时器。1秒的间隔会触发渲染计数+1。如果组件销毁后不清除定时器,会一直消耗资源。importReact,{useState,useEffect}from"react"importReactDOMfrom"react-dom"constApp=()=>{let[index,setIndex]=useState(0)useEffect(()=>{lettimer=setInterval(())=>{setIndex(prev=>prev+1)console.log('定时器正在运行...')},1000)return()=>clearInterval(timer)},[])return(ReactDOM.unmountComponentAtNode(document.getElementById("root"))}>{index})}exportdefaultApp每次更新数据都会触发组件重新渲染。这里的优化是:组件销毁和清理的时机组件类的组件使用了一个纯组件PureComponent。什么是纯成分?中的引用地址是否相同,比较基本数据类型的值是否相同。为什么不直接进行diff操作,而是先进行浅比??较。浅比较没有性能消耗吗?与diff操作相比,浅比较会消耗更少的性能。diff操作会重新遍历整个virtualDOM树,而浅比较只对当前组件的state和props进行操作。importReactfrom"react"exportdefaultclassAppextendsReact.Component{constructor(){super()this.state={name:"张三"}}updateName(){setInterval(()=>this.setState({name:"张三"}),1000)}componentDidMount(){this.updateName()}render(){return(
)}}classRegularComponentextendsReact.Component{render(){console.log("RegularComponent")return
{this.props.name}
}}classPureChildComponentextendsReact.PureComponent{render(){console.log("PureChildComponent")return
{this.props.name}
}}组件挂载后,每1secondname,我们可以看到RegularComponent一直在渲染,即使数据没有改变。PureChildComponent只渲染一次,所以使用纯组件会比较props状态,相同的数据不会重新渲染。shouldComponentUpdate纯组件只能进行浅比较。要执行深度比较,请使用shouldComponentUpdate,它用于编写自定义比较逻辑。返回true重新渲染组件,返回false防止重新渲染。函数的第一个参数是nextProps,第二个参数是nextState。importReactfrom"react"exportdefaultclassAppextendsReact.Component{constructor(){super()this.state={name:"张三",age:20,job:"服务员"}}componentDidMount(){setTimeout(()=>this.setState({job:"chef"}),1000)}shouldComponentUpdate(nextProps,nextState){if(this.state.name!==nextState.name||this.state.age!==nextState.age){returntrue}returnfalse}render(){console.log("rendering")let{name,age}=this.statereturn
{name}{age}
}}即使继承自Component的组件定时器一直在修改数据,也不会触发纯函数组件的重新渲染。使用React.memo优化性能。memo的基本用途是将函数组件变成纯组件,对当前的props和上次的props做一个浅层的比较。如果相同会阻止组件重新渲染。importReact,{memo,useEffect,useState}from"react"functionShowName({name}){console.log("showNamerender...")返回
{name}
}constShowNameMemo=memo(ShowName)functionApp(){const[index,setIndex]=useState(0)const[name]=useState("张三")useEffect(()=>{setInterval(()=>{setIndex(prev=>prev+1)},1000)},[])return(
{index}
)}导出默认的Appmemo转账比较逻辑(使用memo方法自定义比较逻辑,进行深度比较。)importReact,{memo,useEffect,useState}from"react";functionShowName({person}){console.log("showNamerender...");return(
{person.name}丨{person.job}
);}functioncomparePerson(prevProps,nextProps){if(prevProps.person.name!==nextProps.person.name||prevProps.person.age!==nextProps.person.age){returnfalse}returntrue}constShowNameMemo=memo(ShowName,comparePerson);functionApp(){const[person,setPerson]=useState({name:"张三",工作:“开发人员”});useEffect(()=>{setInterval(()=>{setPerson((data)=>({...data,name:"浩轩"}));},1000);},[]);return(
);}exportdefaultApp;使用组件延迟加载使用组件延迟加载可以减少bundle文件的大小并加快组件渲染。路由组件懒加载详细答案参考前端进阶面试题lazy(()=>import(/*webpackChunkName:"Home"*/"./Home"))constList=lazy(()=>import(/*webpackChunkName:"List"*/"./List"))functionApp(){return(
HomeListLoading