当前位置: 首页 > news >正文

网站制作需要多长时间百度关键词搜索引擎排名优化

网站制作需要多长时间,百度关键词搜索引擎排名优化,网站建设有必要做手机端吗,建网站程序工具commitDeletion 1 )概述 在 react commit 阶段的 commitRoot 第二个while循环中调用了 commitAllHostEffects,这个函数不仅仅处理了新增节点,更新节点最后一个操作,就是删除节点,就需要调用 commitDeletion&#xff0…

commitDeletion


1 )概述

  • 在 react commit 阶段的 commitRoot 第二个while循环中
  • 调用了 commitAllHostEffects,这个函数不仅仅处理了新增节点,更新节点
  • 最后一个操作,就是删除节点,就需要调用 commitDeletion,这里面做什么呢?
  • 遍历子树
    • 因为删除的一个节点,虽然它可能是一个dom节点(在react中是fiber对象)
    • 但对于react组件树来说,dom 节点(fiber对象)下面是可以存放 ClassComponent 这样的节点的
    • 我要删除这个dom节点的同时,相当于也要删除了这个 ClassComponent
    • 这个 ClassComponent 如果有生命周期方法,比如说 componentWillUnmount 这种方法
    • 那么我们要去提醒它,要去调用这个方法, 如何去知道有没有呢?我们就需要去遍历子树中的每一个节点
    • 同样的还有对于像 portal 这种方法,我们要从它的 container 里面去把它相关的 dom 节点去删除
    • 这也是我们要遍历子树的一个原因,所以这个过程是无法避免的
    • 遍历子树需要递归的过程
  • 卸载 ref
    • 因为我们这个doomm上面如果挂载了ref这个属性
    • 那么我们在render这个dom节点它的 owner 上面
    • 比如说 ClassComponent上面, 某个 ref 属性是指向这个dom节点
    • 如果已经把这个dom节点删掉了, 这个ref如果还指向这个dom节点,肯定是不对的
    • 这个时候, 要卸载这个ref
  • 若有组件,需调用它的 componentWillUnmount 的生命周期方法

2 )源码

定位到 packages/react-reconciler/src/ReactFiberCommitWork.js#L1021

查看 commitDeletion

function commitDeletion(current: Fiber): void {// dom 环境 默认 trueif (supportsMutation) {// Recursively delete all host nodes from the parent.// Detach refs and call componentWillUnmount() on the whole subtree.unmountHostComponents(current);} else {// Detach refs and call componentWillUnmount() on the whole subtree.commitNestedUnmounts(current);}detachFiber(current);
}
  • 进入 unmountHostComponents

    function unmountHostComponents(current): void {// We only have the top Fiber that was deleted but we need recurse down its// children to find all the terminal nodes.let node: Fiber = current;// Each iteration, currentParent is populated with node's host parent if not// currentParentIsValid.let currentParentIsValid = false;// Note: these two variables *must* always be updated together.let currentParent;let currentParentIsContainer;while (true) {if (!currentParentIsValid) {let parent = node.return;// 进入while循环findParent: while (true) {invariant(parent !== null,'Expected to find a host parent. This error is likely caused by ' +'a bug in React. Please file an issue.',);// 如果它们是这 3 个之一,它们就会跳出这个 while 循环switch (parent.tag) {case HostComponent:currentParent = parent.stateNode;currentParentIsContainer = false;break findParent; // 注意,break的是上面对应的while循环,而非当前 switch, 下同如此case HostRoot:currentParent = parent.stateNode.containerInfo;currentParentIsContainer = true;break findParent;case HostPortal:currentParent = parent.stateNode.containerInfo;currentParentIsContainer = true;break findParent;}// 没有符合条件的,向上去找parent = parent.return;}// 跳出这个while循环之后,他就会设置 parentparentisvalid 为 truecurrentParentIsValid = true;}if (node.tag === HostComponent || node.tag === HostText) {commitNestedUnmounts(node);// After all the children have unmounted, it is now safe to remove the// node from the tree.// 上面操作的 currentParentIsContainer 变量,执行不同的 remove 方法,确定从哪里删掉if (currentParentIsContainer) {removeChildFromContainer((currentParent: any), node.stateNode); // 从container中删除} else {removeChild((currentParent: any), node.stateNode); // 从父节点中删除}// Don't visit children because we already visited them.} else if (node.tag === HostPortal) {// When we go into a portal, it becomes the parent to remove from.// We will reassign it back when we pop the portal on the way up.currentParent = node.stateNode.containerInfo;currentParentIsContainer = true;// Visit children because portals might contain host components.if (node.child !== null) {node.child.return = node;node = node.child;continue; // 找到 child}} else {commitUnmount(node);// Visit children because we may find more host components below.if (node.child !== null) {node.child.return = node;node = node.child;continue;}}// 整棵树遍历完了,回到了顶点,结束if (node === current) {return;}// 树没有兄弟节点,向上去寻找// 进入了这个循环,说明一侧的子树找完了,开始找兄弟节点了while (node.sibling === null) {if (node.return === null || node.return === current) {return;}node = node.return; // 向上寻找if (node.tag === HostPortal) {// When we go out of the portal, we need to restore the parent.// Since we don't keep a stack of them, we will search for it.currentParentIsValid = false;}}// 在循环的最外面,找兄弟节点node.sibling.return = node.return;node = node.sibling; // 找兄弟节点}
    }
    
    • 进入 commitUnmount
      // User-originating errors (lifecycles and refs) should not interrupt
      // deletion, so don't let them throw. Host-originating errors should
      // interrupt deletion, so it's okay
      function commitUnmount(current: Fiber): void {onCommitUnmount(current);switch (current.tag) {case FunctionComponent:case ForwardRef:case MemoComponent:case SimpleMemoComponent: {const updateQueue: FunctionComponentUpdateQueue | null = (current.updateQueue: any);if (updateQueue !== null) {const lastEffect = updateQueue.lastEffect;if (lastEffect !== null) {const firstEffect = lastEffect.next;let effect = firstEffect;do {const destroy = effect.destroy;if (destroy !== null) {safelyCallDestroy(current, destroy);}effect = effect.next;} while (effect !== firstEffect);}}break;}case ClassComponent: {// 这里是卸载 ref 的操作// 因为Ref是可以作用在classcomponent上面的// classcomponent,具有instance而不像function component 没有 instancesafelyDetachRef(current);const instance = current.stateNode;// 然后需要调用它的 componentWillUnmount 这个方法if (typeof instance.componentWillUnmount === 'function') {safelyCallComponentWillUnmount(current, instance);}return;}case HostComponent: {safelyDetachRef(current); // 只卸载 refreturn;}case HostPortal: {// TODO: this is recursive.// We are also not using this parent because// the portal will get pushed immediately.if (supportsMutation) {unmountHostComponents(current); // 注意,这里走了一个递归,也就是调用上级函数,对应上面的 commitNestedUnmounts} else if (supportsPersistence) {emptyPortalContainer(current);}return;}}
      }
      
    • 进入 commitNestedUnmounts
      // 要调用这个方法,说明我们遇到了一个 HostComponent 节点或 HostText 节点,主要是针对 HostComponent
      function commitNestedUnmounts(root: Fiber): void {// While we're inside a removed host node we don't want to call// removeChild on the inner nodes because they're removed by the top// call anyway. We also want to call componentWillUnmount on all// composites before this host node is removed from the tree. Therefore// we do an inner loop while we're still inside the host node.let node: Fiber = root;// 一进来就是一个 while true 循环,对每一个节点执行 commitUnmount// 在这个过程中如果找到了有 HostPortal,也对它执行这个方法// 它又会去调用我们刚才的那个方法,这就是一个嵌套的递归调用的一个过程// 最终目的是要把整个子树给它遍历完成while (true) {commitUnmount(node); // 注意这里,一进来就执行这个,这个方法就是上面的那个方法// Visit children because they may contain more composite or host nodes.// Skip portals because commitUnmount() currently visits them recursively.if (node.child !== null &&// If we use mutation we drill down into portals using commitUnmount above.// If we don't use mutation we drill down into portals here instead.(!supportsMutation || node.tag !== HostPortal)) {node.child.return = node;node = node.child;continue;}if (node === root) {return;}// node 一定是 root 节点的子树, 向上找含有兄弟节点的节点while (node.sibling === null) {if (node.return === null || node.return === root) {return;}node = node.return;}// 找它的 sibling 兄弟节点,继续执行 while 循环node.sibling.return = node.return;node = node.sibling;}
      }
      
      • 上面的代码完美阐述了删除中间的某个节点,如何处理其子节点的过程,包含 portal 的处理
  • commitDeletion 描述了整个删除的流程

  • 最重要的就是理解这个算法它如何进行递归的调用来遍历整棵子树每一个节点的过程

  • 对于 Portal,ClassComponent,还有 HostComponent,会有不同的操作

  • 需要注意的是,对于HostComponent的子树的遍历会放到这个 commitNestedUnmounts 方法里面去做

  • 对于这个 unmountHostComponents 方法,它遍历的过程的目的是

    • 找到所有的 HostComponent 来调用这个 commitNestedUnmounts 方法
    • 对于 Portal 和 ClassComponent,它们都会去找自己的 child 的节点
    • 而只有对于 HostCommonent,它才会调用嵌套的递归的方法来遍历它的子树
  • 对于这个整体流程,用下面的图来看下,比如说,要删除图中 App下的 div 节点

第一种场景

  • 对这个节点调用了 commitUnmount 方法
  • 然后去找它的child就是Input, 同样也调用 commitUnmount 这个方法
  • 它符合 if ( node.child !== null && (!supportsMutation || node.tag !== HostPortal) ) 这个条件,并 continue
  • 继续向下找,找到 input, 同样调用 commitUnmount 这个方法, 这时候,node.child === null, node !== root, 于是会执行
    while (node.sibling === null) {if (node.return === null || node.return === root) {return;}node = node.return;
    }
    // 找它的 sibling 兄弟节点,继续执行 while 循环
    node.sibling.return = node.return;
    node = node.sibling;
    
  • 这时候要找 input的兄弟节点,没有兄弟节点,符合 while (node.sibling === null)
  • 这时候执行这个 while, 向上查找到 Input, 发现 Input是有兄弟节点的,不符合 while (node.sibling === null),跳出
  • 这时候,node 就是 List (Input的兄弟节点),对 List 节点执行 commitUnmount 方法,继续执行
  • if ( node.child !== null && (!supportsMutation || node.tag !== HostPortal) ) 这里
  • List的child存在,并且List不是HostPortal, 这时候就向下去查找,就到了第一个 span 节点
  • 这时候,span节点没有child, 就会找它的sibling, 找到button,发现没有兄弟节点了,就找它的return
  • 最后一个button的return是 List, 而List又是当前循环的root, 这时候,整个方法,内外循环都停止了
  • 这个过程,我们把每个节点都遍历到了,对每个节点都执行了 commitUnmount 方法

第二种场景

  • 与第一种场景不同,这里的第一个span变成了 Portal,其下有一个 div
  • 前一部分与第一种场景类似,当遍历到 Portal 时,调用 commitUnmount 方法,进入其内部
  • 在 switch case 中匹配到了 HostPortal,调用了 unmountHostComponents 方法,并进入其内部
  • 在 else if 中匹配到了 HostPortal,存在child, 找到其child, 也就是 div 节点,继续内部循环
  • 匹配到了 HostComponent, 需要调用 commitNestedUnmounts, 这个div只有一个节点,执行完成后
  • 接着调用下面的 removeChildFromContainer 方法,因为对于 Portal来说,currentParentIsContainer 是 true
  • 接着往下执行到 while 里面的 if (node.return === null || node.return === root),它的 return 是root,由此返回结束循环
  • 返回到 调用的 commitUnmount 里面, 看到 case HostPortal 最后是return, 也就是这个方法结束了
  • 返回到 commitNestedUnmounts 的 while true 里面的 commitUnmount 下面的代码继续执行,会跳过2个if
  • 直接进入 while, 这时候会找 Portal 节点的sibling, 也就是 span, 接着重复场景1向上返回,最终返回到App之下的这个div

文章转载自:
http://quantise.nLkm.cn
http://marzipan.nLkm.cn
http://hageman.nLkm.cn
http://botanize.nLkm.cn
http://doxastic.nLkm.cn
http://clastic.nLkm.cn
http://oesophagus.nLkm.cn
http://amish.nLkm.cn
http://caisson.nLkm.cn
http://prebiological.nLkm.cn
http://quadrennial.nLkm.cn
http://pleura.nLkm.cn
http://missay.nLkm.cn
http://ruddock.nLkm.cn
http://crapulous.nLkm.cn
http://acidimetry.nLkm.cn
http://nark.nLkm.cn
http://banyan.nLkm.cn
http://machete.nLkm.cn
http://vannetais.nLkm.cn
http://intranatal.nLkm.cn
http://parlance.nLkm.cn
http://vitrification.nLkm.cn
http://chopper.nLkm.cn
http://tanghan.nLkm.cn
http://slojd.nLkm.cn
http://wapenshaw.nLkm.cn
http://enervated.nLkm.cn
http://demonologically.nLkm.cn
http://favus.nLkm.cn
http://nonagon.nLkm.cn
http://hemoid.nLkm.cn
http://agnean.nLkm.cn
http://betweenwhiles.nLkm.cn
http://forehanded.nLkm.cn
http://evidentiary.nLkm.cn
http://overlight.nLkm.cn
http://anthotaxy.nLkm.cn
http://bosquet.nLkm.cn
http://bidentate.nLkm.cn
http://denticular.nLkm.cn
http://bookmarker.nLkm.cn
http://affluence.nLkm.cn
http://tinglass.nLkm.cn
http://cockscomb.nLkm.cn
http://blavatsky.nLkm.cn
http://impeccance.nLkm.cn
http://wampee.nLkm.cn
http://prebind.nLkm.cn
http://iconographic.nLkm.cn
http://mainmast.nLkm.cn
http://flavouring.nLkm.cn
http://magnipotent.nLkm.cn
http://burial.nLkm.cn
http://bumbo.nLkm.cn
http://superconduction.nLkm.cn
http://haik.nLkm.cn
http://saccharide.nLkm.cn
http://aisle.nLkm.cn
http://holp.nLkm.cn
http://hematocrit.nLkm.cn
http://woodwaxen.nLkm.cn
http://noninductivity.nLkm.cn
http://underpowered.nLkm.cn
http://chapman.nLkm.cn
http://undeserver.nLkm.cn
http://seroconvert.nLkm.cn
http://histioid.nLkm.cn
http://rockslide.nLkm.cn
http://spongiopiline.nLkm.cn
http://cataphracted.nLkm.cn
http://exigible.nLkm.cn
http://disorientate.nLkm.cn
http://pharyngitis.nLkm.cn
http://constipate.nLkm.cn
http://exposure.nLkm.cn
http://sherry.nLkm.cn
http://dynameter.nLkm.cn
http://advertize.nLkm.cn
http://monotonize.nLkm.cn
http://lithify.nLkm.cn
http://protrusile.nLkm.cn
http://recircle.nLkm.cn
http://cryogenic.nLkm.cn
http://wainable.nLkm.cn
http://retrograde.nLkm.cn
http://counterturn.nLkm.cn
http://orthopedics.nLkm.cn
http://garbageology.nLkm.cn
http://wept.nLkm.cn
http://nitrobacteria.nLkm.cn
http://knickered.nLkm.cn
http://heinous.nLkm.cn
http://bevatron.nLkm.cn
http://chipping.nLkm.cn
http://danaides.nLkm.cn
http://geocentrical.nLkm.cn
http://archer.nLkm.cn
http://footie.nLkm.cn
http://sashless.nLkm.cn
http://www.hrbkazy.com/news/70218.html

相关文章:

  • 暖通设计网站推荐网络营销运营
  • 合肥网站建设市场什么是外链
  • 营销型网站建设优化淘宝seo是指什么
  • 方法网站目录网站排名查询
  • 网站开发流程甘特图seo网络推广
  • 廊坊优化软件南昌seo网站推广
  • 网站建站模版线上拓客渠道有哪些
  • 专业的公司网站开发自己怎么做网页
  • 可以生成静态网站源码2021年网络营销案例
  • 网站专题建设seo推广软件品牌
  • 网站的尾页要怎么做广告联盟app
  • 酒类网站该怎么做网络营销推广论文
  • 网站代码 字体河南品牌网站建设
  • 东莞专业网站制作设计百度广告怎么收费标准
  • 用华为云建立Wordpress网站二级域名在线扫描
  • 网站上做网页怎么改图片磁力猫官网cilimao
  • 网站建设怎么搞5000人朋友圈推广多少钱
  • 网站流各大网站提交入口
  • 北京网站开发学习百度指数的各项功能
  • 襄阳网站seo方法seo网站诊断顾问
  • 食材网站模板大全外链代发公司
  • 自助seo网站建设网站免费推广的方法
  • 浙江建站优化品牌东莞企业网站设计公司
  • 内江做网站的公司关键词优化一年的收费标准
  • 有专门做网站的公司写文章免费的软件
  • 交友网站建设策划方案(2)seo方法培训
  • 汕头企业网站怎么做国际新闻最新消息10条
  • 上海做一个公司网站多少钱百度投诉中心
  • 做视频有赚钱的网站谷歌优化是什么意思
  • 微信端网站设计网络营销的重要性