最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React 学习之渲染过程

    正文概述 掘金(suressk)   2021-07-20   521

    渲染原理

    术语描述:

    渲染: 生成用于显示的对象,以及将这些对象形成真实的 DOM 对象

    1. React 元素 (React Element):通过 React.createElement 创建 (语法糖:JSX 表达式创建);如: <div>React Element</div><App />

    2. React 节点 (React Component):专门用于渲染到 UI 界面的对象 (Virtual DOM),React 会通过 React 元素 创建 React 节点,ReactDOM 一定是根据 React 节点来渲染页面的

      节点类型:

      • React DOM 节点 (Virtual DOM Node):创建该节点的 React 与元素类型是一个 字符串 ("div", "h1'等)
      • React 组件节点 (React ComponentNode):创建该节点的 React 与元素类型是一个 函数 或一个 (比如我们封装的函数组件或类组件等)
      • React 文本节点 (React TextNode):由字符串、数字创建
      • React 空节点 (React EmptyNode)null, undefined, false, true
      • React 数组节点 (React ArrayNode):由数组创建

    首次渲染 (新节点挂载阶段)

    1. 通过参数的值创建节点 ReactDOM.render(参数, MONT_NODE)

    2. 根据不同的节点,做不同的事情

      • 文本节点:通过 document.createTextNode() 创建真实的文本节点
      • 空节点:不创建真实 DOM
      • 数组节点:遍历数组,对每一项递归进行创建节点 (回第 ① 步,直到遍历结束)
      • DOM 节点:JSX 解析生成的对象 (React 元素),通过 document.createElement() 创建真实 DOM 对象,然后遍历对应 React 元素的 children 属性(对象或数组),递归操作 (回第1步,直到遍历结束)
      • 组件节点函数组件:调用函数 (该函数必须返回可以生成节点的内容),将该函数的返回结果递归生成节点 (同上);类组件:创建该类的实例,立即调用对象的生命周期方法 static getDerivedStateFromProps,运行该对象的 render 方法,得到节点对象,递归操作;将该组件的 componentDidMount 加入到执行队列 (先进先执行),当整个虚拟 DOM 树全部构建完毕,并且将真实的 DOM 对象加入到容器中后,遍历该队列执行
    3. 生成虚拟 DOM 树后,将该树保存起来,以便后续使用 (diff)

    4. 将之前生成的真实 DOM 对象,加入到页面的容器中

    更新节点

    节点更新时机:

    1. 重新调用 ReactDOM.render() 方法,完全重新生成节点树 (虚拟 DOM 树),触发根节点的更新

    2. 在类组件中调用 this.setState() 更新状态,会导致该实例所在的节点更新

    3. hook 涉及的更新后续再说~

    对比更新

    1. 如果调用 ReactDOM.render() 方法,对比更新根节点(diff)

    2. 如果调用 this.setState() 方法

      • 运行生命周期函数 static getDerivedStateFromProps
      • 运行生命周期函数 shouldComponentUpdate,若 返回 false,终止当前流程
      • 运行 render,得到一个新的节点,进入该新节点的 对比更新
      • 将生命周期函数 getSnapshotBeforeUpdate 加入执行队列,等待执行
      • 将生命周期函数 componentDidUpdate 加入执行队列 (与上面这步不是同一个队列),等待执行

    对比更新的后续步骤:

    • 更新虚拟 DOM 树
    • 完成真实 DOM 的更新
    • 依次调用执行队列中的 compoentDidMount (产生的新组件挂载)
    • 依次调用执行队列中的 getSnapshotBeforeUpdate
    • 依次调用执行队列中的 componentDidUpdate
    • 依次调用执行队列中的 componentWillUnmount (被移除的子节点才会推入队列)

    对比更新:将新产生的节点,与之前虚拟 DOM 中的节点进行对比,发现差异,进行更新

    对比假设

    React 为了提高对比效率,做出以下假设:

    1. React 节点的位置不会进行层级的移动 (对比时,直接找到旧树中对应位置的节点进行对比)

    2. 不同的节点类型会生成不同的结构

      • 相同的节点类型:节点本身类型相同 (如文本类型,DOM节点);如果是组件节点,组件类型也得相同 (类 / 函数);若是由 React 元素生成,type 值必须是一致的
    3. 多个兄弟节点通过唯一标识 (key) 来确定对比的新节点

      • key 值用于通过旧节点来寻找应该对比的新节点,如果某个旧节点有 key 值,则其更新时,会寻找相同层级中具有相同 key 值的节点 (若未找到,则进入未找到对比节点的流程)

    找到对比节点

    判断节点类型是否一致

    1. 一致:根据不同的节点做不同的事:

      • 空节点:不做任何事;
      • DOM 节点:重用之前生成的真实 DOM 对象,将其属性的变化进行记录 (此时不会更新 DOM),遍历该新的 React 元素的子元素,递归对比更新;
      • 文本节点:直接重用之前的真实 DOM 对象,记录变化的 nodeValue 值;
      • 函数组件节点:重新调用函数,得到一个节点对象,进入递归对比更新;
      • 类组件节点:重用之前的实例,依次调用 static getDerivedStateFromProps, shouldComponentUpdate (若返回false,终止对比),否则运行 render,进入递归对比更新,将该对象的 getSnapshotBeforeUpdate, componentDidUpdate 加入相应的队列,等待执行;
      • 数组节点:遍历数组,进行递归对比更新
    2. 不一致:整体上,卸载旧的节点,重新创建新的节点 (先创建新节点,后卸载旧节点)。旧节点:

      • 空节点, 文本节点, DOM 节点, 数组节点, 函数组件节点:直接舍弃旧节点,创建新节点 (进入 新节点挂载阶段);
      • 类组件节点:直接舍弃旧节点,调用该节点的 componentWillUnmount 函数,递归卸载子节点

    未找到对比目标

    新的虚拟 DOM 树中有 新的节点删除或添加,即:创建新加入的节点,卸载多余的节点 (还是上面挂载跟卸载的流程)


    起源地下载网 » React 学习之渲染过程

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元