美文网首页
React Virtual DOM Diff

React Virtual DOM Diff

作者: 冬青_2f75 | 来源:发表于2018-12-07 18:39 被阅读0次

假设我们的DOM长这个样子

<ul class="list">
  <li>item1</li>
  <li>item2</li>
</ul>

如果用JS Object表达上面的 dom,表达方式如下

{
  type: 'ul',
  props: { 'class': 'list' },
  children: [{
    type: 'li', props: {}, children: ['item1']
  }, {
    type: 'li', props: {}, children: ['item2']
  }]
}

通过以下的函数,我们将虚拟DOM转换成真实的DOM

function createElement(node) {
    if (typeof node === 'string') {
        return document.createTextNode(node)
    }
    const $el = document.createElement(node.type)
    node.children
      .map(createElement)
      .forEach($el.appendChild.bind($el))  
    return $el
}

现在我们考虑Diff,假设我们有两个virtual trees ----old and new, 我们考虑下面几种不一样的情况:

  1. new tree里面有新的元素


    屏幕快照 2018-12-07 下午6.02.16.png

    实现方式如下:

 function updateElement($parent, newNode, oldNode) {
    if (!oldNode) {
      $parent.appendChild(createElement(newNode))
    }
}
  1. new tree里面删除了元素


    屏幕快照 2018-12-07 下午6.05.46.png

    当要删除一个元素时,我们不知道真实的DOM节点,但此时我们可以知道这个节点的position,所以可以通过position拿到真是的DOM,然后删掉它
    实现方式如下:

function updateElement($parent, newNode, oldNode, index = 0) {
  if (!newNode) {
      $parent.removeChild(
          $parent.childNodes[index]
      )
  }
}
  1. node 本身变了


    屏幕快照 2018-12-07 下午6.14.02.png

    首先,我们来检测change

function change(node1, node2) {
    return typeof node1 !=== typeof node2 ||
      typeof node1 === 'string' && node1 !=== node2 ||
      node1.type !== node2.type
}
function updateElement($parent, newNode, oldNode, index) {
    if (change(newNode, oldNode)) {
        $parent.replaceChild(
            createElement(newNode),
            $parent.childNodes[index]
        )
    }
}
  1. node本身没变,但是其children有可能变了


    屏幕快照 2018-12-07 下午6.29.24.png

    需要递归的比较children

function updateElement($parent, newNode, oldNode, index) {
  if (newNode.type) {
      const newLength = newNode.children.length
      const oldLength = oldNode.children.length
      for(let i = 0; i < newLength || i < oldLength; i++) {
        updateElement(
            $parent.childNode[index],
            newNode.children[i],
            oldNode.children[i],
            i
        )
      }
  }
}

updateElement 最终的实现方式如下:

function updateElement($parent, newNode, oldNode, index = 0) {
  if (!oldNode) {
    $parent.appendChild(
      createElement(newNode)
    );
  } else if (!newNode) {
    $parent.removeChild(
      $parent.childNodes[index]
    );
  } else if (changed(newNode, oldNode)) {
    $parent.replaceChild(
      createElement(newNode),
      $parent.childNodes[index]
    );
  } else if (newNode.type) {
    const newLength = newNode.children.length;
    const oldLength = oldNode.children.length;
    for (let i = 0; i < newLength || i < oldLength; i++) {
      updateElement(
        $parent.childNodes[index],
        newNode.children[i],
        oldNode.children[i],
        i
      );
    }
  }
}

参考文献:
https://medium.com/@deathmood/how-to-write-your-own-virtual-dom-ee74acc13060

相关文章

  • react(其一)

     react、reactjs、react native、virtual dom、diff算法、redux....,...

  • vitual-dom原理与简单实现

    前言 目前广为人知的React和Vue都采用了virtual-dom,Virtual DOM凭借其高效的diff算...

  • 理解React的核心——Virtual DOM和Diff

    React通过JS对象模拟原生DOM,加上DOM Diff 极大提升了DOM操作的性能。Virtual DOM:R...

  • React基础3--diff算法

    本来想深入说一下virtual dom 与diff,但是最近很忙,就简单聊聊react的diff算法吧。 diff...

  • React Virtual DOM Diff

    假设我们的DOM长这个样子 如果用JS Object表达上面的 dom,表达方式如下 通过以下的函数,我们将虚拟D...

  • 学习笔记之React 虚拟DOM与diff算法

    React 中最值得称道的部分莫过于 Virtual DOM 与 diff 的完美结合,特别是其高效的 diff ...

  • React Diff 过程

    Diff 的作用 React Diff 会帮助我们计算出 Virtual DOM 中真正变化的部分,并只针对该部分...

  • React进阶篇(三)diff算法

    如何计算Virtual Dom中真正变化的部分,这就需要diff算法。 Virtual Dom配合高效的diff算...

  • diff之React:Virtual DOM

    一、读懂diff diff是Unix/Linux系统的一个很重要的工具程序。它用来比较两个文本文件的差异,是代码版...

  • React-diff

    React是根据Virtual DOM的对比来更新DOM的。这种用来对比的方法被称为diff算法,该算法由fb进一...

网友评论

      本文标题:React Virtual DOM Diff

      本文链接:https://www.haomeiwen.com/subject/mrhxhqtx.html