资讯专栏INFORMATION COLUMN

从React渲染流程分析Diff算法

lykops / 3458人阅读

摘要:什么是虚拟在中,执行的结果得到的并不是真正的节点,结果仅仅是轻量级的对象,我们称之为。后来产出的架构模式,期望从代码组织方式来降低维护难度。

1、什么是虚拟DOM
在React中,render执行的结果得到的并不是真正的DOM节点,结果仅仅是轻量级的JavaScript对象,我们称之为virtual DOM。

简单的说,其实所谓的virtual DOM就是JavaScript对象到Html DOM节点的映射;即使用JavaScript对象将Html结构表示出来,而这个对象就是virtual DOM。

eg:

Html:

  • Item 1
  • Item 2

JavaScript对象表示(virtual DOM)

{
  tagName: "ul",
  props: {
    id: "list"
  },
  children: [
    {tagName: "li", props: {class: "item"}, children: ["Item 1"]},
    {tagName: "li", props: {class: "item"}, children: ["Item 2"]},
  ]
}
2、什么时候会生成到virtual DOM

React生命周期拥有装载、更新、卸载的三个阶段;附上一张React生命周期图

前面提到:render执行的结果得到的并不是真正的DOM节点,结果仅仅是轻量级的JavaScript对象,即在render函数调用时将会创建出虚拟DOM;

class Tab extends React.Component {
    render() {
        React.createElement(
          "p",
          { className: "class"},
          "Hello React"
        )
    }
}

通过React.createElemen创建出虚拟DOM,而该函数只在Render函数中调用,所以在React装载和更新的过程中才会有虚拟DOM的生成;至于挂载到真实DOM自然而然是ReactDom.render函数啦。


3、virtual DOM如何实现

实现其实很简单,主要是定义一个函数并把我们传进去的参数组成一个React元素对象,而type就是我们传进去的组件类型,可以是一个类、函数或字符串(如"div")

React大致源码:

function createElement(type, config, children) {
  let propName;

  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if (config != null) {
    if (hasValidRef(config)) {
      //  如果有ref,将它取出来
      ref = config.ref;
    }
    if (hasValidKey(config)) {
      //  如果有key,将它取出来
      key = "" + config.key;
    }

    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source;
    
    for (propName in config) {
      if (
        hasOwnProperty.call(config, propName) &&
        !RESERVED_PROPS.hasOwnProperty(propName)
      ) {
        //  将除ref,key等这些特殊的属性放到新的props对象里
        props[propName] = config[propName];
      }
    }
  }

  //  获取子元素
  const childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    props.children = childArray;
  }

  //  添加默认props
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }
  
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );
}

const ReactElement = function(type, key, ref, self, source, owner, props) {
  //  最终得到的React元素
  const element = {
    // This tag allows us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE,

    // Built-in properties that belong on the element
    type: type,
    key: key,
    ref: ref,
    props: props,

    // Record the component responsible for creating this element.
    _owner: owner,
  };

  return element;
};

打印出组件:

4、为什么需要使用virtual DOM

DOM管理历史阶段:

JS 或者 jQuery 操作 DOM: 当应用程序越来越复杂,需要在JS里面维护的字段也越来越多,需要监听事件和在事件回调用更新页面的DOM操作也越来越多,应用程序会变得非常难维护。

后来产出 MVC、MVP 的架构模式,期望从代码组织方式来降低维护难度。但是 MVC 架构并没办法减少维护的状态,也没有降低状态更新时需要对页面的更新操作,你需要操作的DOM还是需要操作,只是换了个地方。

既然状态改变了要操作相应的DOM元素,为什么不做一个东西让视图和状态进行绑定,状态变更了视图自动变更。这就是后来人们想出了 MVVM 模式,只要在模版中声明视图组件是和什么状态进行绑定的,双向绑定引擎就会在状态更新的时候自动更新视图;

但MVVM双向数据绑定并不是唯一的办法,还有一个非常直观的方法:一旦状态发生了变化,就用模版引擎重新渲染整个视图,然后用新的视图更换掉旧的视图。

React采用的就是第四种模式;但是我们都知道对于操作DOM成本太高,而相对操作JavaScript就快速多了,而Html DOM可以很简单的用JavaScript对象表示出来(Virtual DOM就这样诞生了)

这样的做法会导致很多的问题,最大的问题就是这样做会很慢,因为即使一个小小的状态变更都要重新构造整棵 DOM,性价比太低;而React Virtual DOM在状态更新过程加了一些特别的操作来避免整棵 DOM 树变更(它就是接下来的Diff算法)。

接下来的Diff算法即将更新,敬请期待~~~

“积跬步、行千里”—— 持续更新中~,喜欢留下个赞哦!

往期经典好文:

团队合作必备的Git操作

谈谈Js前端规范化

相关专栏推荐:

React学习之路

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/54612.html

相关文章

  • react精髓之一---diff算法

    摘要:传统算法的一大特点就是虚拟的算法,下图为实现流程图。如果的子节点仍有子节点依旧顺次执行。我们来观察下复杂度传统算法的复杂度为,单纯从看,复杂度不到,但实际上。通过制定大胆的策略,将复杂度的问题转换成复杂度的问题。 从react渲染开始:   在说react虚拟dom之前我们先来看看react渲染过程,下面链接是根据源码渲染过程写的简写版。http://1.sharemandy.sina...

    Miyang 评论0 收藏0
  • React渲染流程分析Diff算法

    摘要:什么是虚拟在中,执行的结果得到的并不是真正的节点,结果仅仅是轻量级的对象,我们称之为。后来产出的架构模式,期望从代码组织方式来降低维护难度。 1、什么是虚拟DOM 在React中,render执行的结果得到的并不是真正的DOM节点,结果仅仅是轻量级的JavaScript对象,我们称之为virtual DOM。 简单的说,其实所谓的virtual DOM就是JavaScript对象到H...

    sutaking 评论0 收藏0
  • react基本原理及性能优化

    摘要:对同一层级的子节点进行处理时,会根据进行简要的复用。二性能优化方案由于中性能主要耗费在于阶段的算法,因此性能优化也主要针对算法。此时最常用的优化方案即为方法。或者直接使用,原理一致。 一、从React原理谈起 react是什么? showImg(https://segmentfault.com/img/bVbcYvf?w=1140&h=384); react是用于构建用户界面的JS框架...

    VincentFF 评论0 收藏0
  • react基本原理及性能优化

    摘要:对同一层级的子节点进行处理时,会根据进行简要的复用。或者直接使用,原理一致。 一、从React原理谈起 react是什么? showImg(https://segmentfault.com/img/bVbcYvf?w=1140&h=384); react是用于构建用户界面的JS框架。因此react只负责解决view层的渲染。 react做了什么? Virtual Dom模型 生命周期...

    pinecone 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<