第
React?模式之纯组件使用示例详解
目录什么是纯组件纯组件解决了什么问题怎么使用纯组件CC:shouldComponentUpdate()和React.PureComponentFC:React.memo()你可能并不需要纯组件
什么是纯组件
纯组件(PureComponent)这概念衍生自纯函数。纯函数指的是返回结果只依赖于传入的参数,且对函数作用域外没有副作用的函数。这种函数在相同参数下,返回结果是不变的。纯函数的返回值能被安全地缓存起来,在下次调用时,跳过函数执行,直接读取缓存。因为函数没有外部副作用,不执行函数对整个程序没有影响。
与纯函数类似,如果一个组件在props和state相同的情况下,每次render的结果都是相同的,那这个组件就是纯组件。也就是说,纯组件的render结果只依赖于props和state,如果两次渲染中,props和state是相同的,那它们的render结果也是一样的。
纯组件解决了什么问题
在理解纯组件有什么用处之前,先来看一下React如何更新组件。
React在更新组件时,会从触发组件开始,递归地调用整颗子树的render函数,构建新的虚拟树。即使子组件的props和state没有变化,render函数还是会被执行。
看这个例子:
constdefaultMessage=Hello!;
functionMessager(){
console.log(renderinparent);
const[messageInput,setMessageInput]=useState(defaultMessage);
const[messageData,setMessageData]=useState({
id:0,
message:,
return(
divclassName=logger
input
value={messageInput}
onChange={(e)=setMessageInput(e.target.value)}
/input
button
()=
setMessageData((preData)=({
id:preData.id+1,
message:messageInput,
发送消息
/button
MessageTextmessage={messageData.message}/
/div
functionMessageText(props){
console.log(renderinchild);
returndiv最新消息:{props.message}/div
连续点击几次按钮:
父组件Messager由于状态更新,需要重新执行render函数来更新组件,这个是符合预期的。子组件MessageText中,第一次更新,由于message属性改变,也需要更新,这个也容易理解。
问题在后面几次更新:
子组件的props没有变化,为什么执行了render函数?render函数执行了,是不是意味着DOM也更新了,只是我们看不出变化?组件在props没有变化时,绘制的视图都是不变的,能不能跳过render函数的执行?
让我一个一个来回答。
Q:为什么需要执行render函数?
A:你的组件可能使用了任何变量,包括全局变量、环境变量等,React没有能力做到监听这些变量,这些变量的变化是React无法感知的。为了保证渲染的视图与数据是一致的,React只能牺牲性能,在每次更新的时候,都去执行render函数,获取最新的render输出。
Q:执行了render函数就一定会更新DOM吗?
A:不一定。render函数的输出结果是React虚拟DOM,执行了render函数会更新虚拟DOM,但React足够聪明,能够比对出浏览器DOM需要更新的地方,让浏览器只进行必要的重绘。这也是React能够保证性能的重要手段。
Q:能避免不必要的render执行吗?
A:可以。如果是class组件(CC),你可以重写shouldComponentUpdate()方法或继承React.PureComponent。如果是函数组件(FC),你可以使用React.m