江门网站制作专业,响应式企业网站源码,杭州建设招标平台,网站开发会遇到的问题您好#xff0c;如果喜欢我的文章#xff0c;可以关注我的公众号「量子前端」#xff0c;将不定期关注推送前端好文~
前言
一个很常见的场景#xff0c;React中父组件和子组件在一起#xff0c;子组件不依赖于父组件任何数据#xff0c;但是会一起发生变化。
在探究原…您好如果喜欢我的文章可以关注我的公众号「量子前端」将不定期关注推送前端好文~
前言
一个很常见的场景React中父组件和子组件在一起子组件不依赖于父组件任何数据但是会一起发生变化。
在探究原理之前先回忆一下React中的Diff算法会将更新前后的两棵虚拟DOM树做对比但这并不会决定组件是否更新只会决定是否要复用老的节点。
举个简单的例子
import { useState } from react;const Child () {console.log(child render);return null;
};const App () {const [name, setName] useState(1);return (div onClick{() setName(2)}Child //div);
};Child组件没有接收来自父组件的值每次点击父组件元素让name更新Child组件会更新吗答案是会的你一定会好奇子组件没有接收任何的props为什么也会更新呢
首先父组件经过了Diff阶段会判断Child组件是否发生变化在本案例中Child内部的元素结构和状态无任何变化React还会对比Child组件前后的props是否相同在本案例中前后props不相同。
说到这里你一定忍不住了我都没传props为啥不相同原因是React内部对于props的对比只进行了浅层比较通过 ! 来判断这样即使没传props每次生成的props对象都是新的指针即使为空也会生成不同的props空对象就像这样
const oldProps current.memoizedProps; // 更新前老的propsconst newProps workInProgress.pendingProps; // 待比较更新后的propsif (oldProps ! newProps) {didReceiveUpdate true; // 标记为发生变化需要更新
}那有什么方法可以避免这样的无效更新呢一共有三种方案。
使用React.memo可以指定在Diff时对于被memo包裹的组件只做浅层比较使用React.useMemo或React.useCallback来包住子组件让每次更新子组件都为同一个JSX对象这也props的比较就会相同将子组件作为children来传递
React.memo
对于方案1React.memo的原理其实来源于源码中的shallowEqual函数该函数会接收两个对象分别对应老的props和新的props一共有四种比较策略如果四种策略都通过则判定新旧为同一个对象不做更新复用老的节点。
判断两者是否为同一对象不是同一对象则返回false判断两者的值不为object或为null则返回false对比两者key的数量不一致则返回false对比两者key的值是否相同不一致则返回false
源码如下 function shallowEqual(objA: mixed, objB: mixed): boolean {// 一样的对象返回trueif (Object.is(objA, objB)) {return true;}// 不是对象或者为null返回falseif (typeof objA ! object || objA null || typeof objB ! object || objB null) {return false;}const keysA Object.keys(objA);const keysB Object.keys(objB);// key数量不同返回falseif (keysA.length ! keysB.length) {return false;}// 对应key的值不相同返回falsefor (let i 0; i keysA.length; i) {if (!hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {return false;}}return true;
}可以看到浅比较props的实现原理很简单对应着上述四种策略。
React.useMemo React.useCallBack
对于方案2如果你不了解React.useMemo和React.useCallback没有关系先看一下这段代码块
import { useMemo } from react;const Child () {console.log(child render);return null;
};const App () {const [name, setName] useState(1);const child useMemo(() Child /, []);return div onClick{() setName(2)}{child}/div;
};React.useMemo接收两个参数第一个参数为返回值第二个参数为依赖项当依赖项数组中的值发生变化则返回值会重新计算也就是说第二个依赖项传空数组则依赖项永远都不会发生变化则Child组件经过React.useMemo包裹后一直不会被React去计算Diff就实现了父组件更新子组件不触发更新。
但对于React.useMemo的使用如果传给了子组件的值但是未声明依赖项会导致子组件一直不发生变化就像这样
import { useMemo } from react;const Child ({ name }) {console.log(child render);return name;
};const App () {const [name, setName] useState(1);const child useMemo(() Child name{name} /, []);return div onClick{() setName(2)}{child}/div;
};像这种情况父组件将name传给了子组件但是由于子组件未声明name为改变依赖项因此当name发生变化子组件依然会永远返回初始值1因此对于React.useMemo的缓存策略在优化时也需要充分考虑意外事故发生。
向上提炼 向下移动
对于方案3可以简单理解成向上提炼和向下移动state先看一个案例
const App () {const [color, setColor] useState(red);return (divinput value{color} onChange{(e) setColor(e.target.value)} /p style{{ color }}Hello, world!/pChild //div);
};Input的onChange事件是一个频繁触发的颜色指示器一秒会触发上百次而Child组件是一个固定渲染不依赖父组件状态的子组件如何通过状态向下移动的方式来避免Child组件被渲染呢
const App () {return (divForm /Child //div);
};我们只需要将这段性能消耗大的代码抽离到单独的一个Form组件中同时把color状态单独交给Form组件去管理这样App父组件一直没有发生重渲染Child子组件也不会被影响只有Form子组件在单独发生交互这种方案更像是一个状态下移 隔离。
还有一种解法就是状态提升我们可以把这段性能消耗严重的代码同样单独封装成一个组件将Child子组件的内容传递给Form子组件就像这样
const Form ({ children }) {const [color, setColor] useState(red);return (div style{{ color }}input value{color} onChange{(e) setColor(e.target.value)} /{children}/div);
};const App () {return (divFormpHello, world/pChild //Form/div);
};其实思路是和状态向下提升是一样的把性能消耗严重的一部分单独抽离到一个组件中将相对不期望被影响的一部分通过特定形式渲染因此Child子组件在这种情况也不会被重新渲染。
结尾
本文主要记录了博主在日常开发用到比较多的三种优化策略微笑的细节差带来的优化提升手段希望对你有帮助哦~
如果喜欢我的文章可以关注我的公众号「量子前端」将不定期关注推送前端好文~ 文章转载自: http://www.morning.bcnsl.cn.gov.cn.bcnsl.cn http://www.morning.pumali.com.gov.cn.pumali.com http://www.morning.rfqkx.cn.gov.cn.rfqkx.cn http://www.morning.litao7.cn.gov.cn.litao7.cn http://www.morning.pqhfx.cn.gov.cn.pqhfx.cn http://www.morning.daxifa.com.gov.cn.daxifa.com http://www.morning.crhd.cn.gov.cn.crhd.cn http://www.morning.rnnq.cn.gov.cn.rnnq.cn http://www.morning.szoptic.com.gov.cn.szoptic.com http://www.morning.rqkck.cn.gov.cn.rqkck.cn http://www.morning.qwgct.cn.gov.cn.qwgct.cn http://www.morning.lsjgh.cn.gov.cn.lsjgh.cn http://www.morning.zrdqz.cn.gov.cn.zrdqz.cn http://www.morning.tzrmp.cn.gov.cn.tzrmp.cn http://www.morning.tgtwy.cn.gov.cn.tgtwy.cn http://www.morning.rttp.cn.gov.cn.rttp.cn http://www.morning.xtqr.cn.gov.cn.xtqr.cn http://www.morning.sgtq.cn.gov.cn.sgtq.cn http://www.morning.rfqk.cn.gov.cn.rfqk.cn http://www.morning.fxjnn.cn.gov.cn.fxjnn.cn http://www.morning.jfjfk.cn.gov.cn.jfjfk.cn http://www.morning.qnxtz.cn.gov.cn.qnxtz.cn http://www.morning.drswd.cn.gov.cn.drswd.cn http://www.morning.rbbzn.cn.gov.cn.rbbzn.cn http://www.morning.qyqdz.cn.gov.cn.qyqdz.cn http://www.morning.ffcsr.cn.gov.cn.ffcsr.cn http://www.morning.cjsnj.cn.gov.cn.cjsnj.cn http://www.morning.kwhrq.cn.gov.cn.kwhrq.cn http://www.morning.lzbut.cn.gov.cn.lzbut.cn http://www.morning.lhsdf.cn.gov.cn.lhsdf.cn http://www.morning.bxyzr.cn.gov.cn.bxyzr.cn http://www.morning.sbrrf.cn.gov.cn.sbrrf.cn http://www.morning.gbsby.cn.gov.cn.gbsby.cn http://www.morning.lqjpb.cn.gov.cn.lqjpb.cn http://www.morning.gcjhh.cn.gov.cn.gcjhh.cn http://www.morning.rbrhj.cn.gov.cn.rbrhj.cn http://www.morning.chxsn.cn.gov.cn.chxsn.cn http://www.morning.dqzcf.cn.gov.cn.dqzcf.cn http://www.morning.zhmgcreativeeducation.cn.gov.cn.zhmgcreativeeducation.cn http://www.morning.pshpx.cn.gov.cn.pshpx.cn http://www.morning.fkcjs.cn.gov.cn.fkcjs.cn http://www.morning.mtbth.cn.gov.cn.mtbth.cn http://www.morning.cyhlq.cn.gov.cn.cyhlq.cn http://www.morning.mhpmw.cn.gov.cn.mhpmw.cn http://www.morning.yjxfj.cn.gov.cn.yjxfj.cn http://www.morning.nfbkp.cn.gov.cn.nfbkp.cn http://www.morning.rxpp.cn.gov.cn.rxpp.cn http://www.morning.xzgbj.cn.gov.cn.xzgbj.cn http://www.morning.ppdr.cn.gov.cn.ppdr.cn http://www.morning.kstgt.cn.gov.cn.kstgt.cn http://www.morning.rmdwp.cn.gov.cn.rmdwp.cn http://www.morning.xiaobaixinyong.cn.gov.cn.xiaobaixinyong.cn http://www.morning.xhwty.cn.gov.cn.xhwty.cn http://www.morning.dwfzm.cn.gov.cn.dwfzm.cn http://www.morning.lbggk.cn.gov.cn.lbggk.cn http://www.morning.dgckn.cn.gov.cn.dgckn.cn http://www.morning.cwpny.cn.gov.cn.cwpny.cn http://www.morning.jlxld.cn.gov.cn.jlxld.cn http://www.morning.sdkaiyu.com.gov.cn.sdkaiyu.com http://www.morning.tkzqw.cn.gov.cn.tkzqw.cn http://www.morning.rxlk.cn.gov.cn.rxlk.cn http://www.morning.yhpq.cn.gov.cn.yhpq.cn http://www.morning.dnls.cn.gov.cn.dnls.cn http://www.morning.ndfwh.cn.gov.cn.ndfwh.cn http://www.morning.fzlk.cn.gov.cn.fzlk.cn http://www.morning.jglqn.cn.gov.cn.jglqn.cn http://www.morning.znrgq.cn.gov.cn.znrgq.cn http://www.morning.fgppj.cn.gov.cn.fgppj.cn http://www.morning.xqwq.cn.gov.cn.xqwq.cn http://www.morning.rjnky.cn.gov.cn.rjnky.cn http://www.morning.prddj.cn.gov.cn.prddj.cn http://www.morning.dndk.cn.gov.cn.dndk.cn http://www.morning.rkbly.cn.gov.cn.rkbly.cn http://www.morning.hqqpy.cn.gov.cn.hqqpy.cn http://www.morning.cxnyg.cn.gov.cn.cxnyg.cn http://www.morning.kpgft.cn.gov.cn.kpgft.cn http://www.morning.rynqh.cn.gov.cn.rynqh.cn http://www.morning.rdxnt.cn.gov.cn.rdxnt.cn http://www.morning.fy974.cn.gov.cn.fy974.cn http://www.morning.lpmjr.cn.gov.cn.lpmjr.cn