• 售前

  • 售后

热门帖子
入门百科

react中的虚拟dom和diff算法详解

[复制链接]
术数古籍专卖疤 显示全部楼层 发表于 2021-10-26 13:06:24 |阅读模式 打印 上一主题 下一主题
假造DOM的作用

首先我们要知道假造dom的出现是为相识决什么题目的,他解决我们平常频仍的直接操纵DOM服从低下的题目。那么为什么我们直接操纵DOM服从会低下呢?
比如我们创建一个div,我们可以在控制台查看一下这个div上自带大概继续了许多属性,尤其是我们使用js操纵DOM的时候,我们的DOM自己就很复杂,js的操纵也会占用许多时间,但是我们控制不了DOM元素自己,因此假造DOM解决的是js操纵DOM这一层面实在解决的是减少了操纵dom的次数
简朴素现假造DOM

假造DOM,见名知意,就是假的DOM,我们真实的DOM挂载在页面上的,而我们的假造DOM则是在内存中的。这个就必要我们把真实的DOM抽象成一个对象放在内存中。这个对象就可以是如下范例:
  1. var element = {
  2.       tagName: 'div',
  3.       props: {
  4.         class: 'box'
  5.       },
  6.       children: {
  7.         {
  8.           tagName: 'p',
  9.           props: {
  10.             class: 'p1'
  11.           },
  12.           children: ['我是p1']
  13.         },
  14.          {
  15.           tagName: 'p',
  16.           props: {
  17.             class: 'p2'
  18.           },
  19.           children: ['我是p2']
  20.         },
  21.         {
  22.           tagName: 'p',
  23.           props: {
  24.             class: 'p3'
  25.           },
  26.           children: ['我是p3']
  27.         },
  28.       }
  29.     }
复制代码
我们想要构造出这样的对象可以自己封装一个构造函数如下:
  1. function Element(tagName, props, children) {
  2.     this.tagName = tagName
  3.     this.props = props
  4.     this.children = children
  5. }
复制代码
有了这个对象,我们必要把这个假造DOM渲染到真实DOM上,可以写出如下方法:
  1. Element.prototype.render = function () {
  2.     const { tagName, props, children } = this
  3.     var el = document.createElement(tagName)
  4.     for (key in props) {
  5.         el.setAttribute(key, props[key])
  6.     }
  7.     children.forEach((item) => {
  8.         const childEl = (item instanceof Element) ?
  9.               item.render() :
  10.         document.createTextNode(item)
  11.         el.appendChild(childEl)
  12.     })
  13.     return el
  14. }
复制代码
最后我们可以new出这个对象调用render()方法然后appendChild到body中就好了:
  1. let virtualDom = new Element('div', { class: 'box' }, [
  2.     new Element('p', { class: 'p1' }, ['我是p1']),
  3.     new Element('p', { class: 'p2' }, ['我是p2']),
  4.     new Element('p', { class: 'p3' }, ['我是p3']),
  5. ])
  6. let a = virtualDom.render()
  7. document.body.appendChild(a)
复制代码
diff算法

首先我们先相识一下diff算法的作用
如果我们的假造dom发生了变革,我们的内存中又会产生新的假造DOM,如果我们直接用这个新的假造DOM结构的话,又会导致许多重复的渲染,因此 这个时候diff算法的作用就体现了出来,diff通过比力新旧两个假造DOM树,找出差异,并且记载下来,然后把记载的差异应用到真实的DOM树上。
原理:
diff算法通过对新旧两颗树举行深度优先遍历,每一个节点都加一个唯一的标识。
这个过程分为2步
       
  • 找出两个树的差异,并记载在一个伪数组里。   
  • 把这些不同应用到真实的DOM树上
对于dom的操纵根本可化为4种范例
       
  • 对节点的删除,移动,添加子节点   
  • 更换节点标签   
  • 对于文本节点,修改节点文本   
  • 修改节点props
下面会用伪代码的形式大致过一下这个流程
  1. // diff 函数,对比两棵树
  2. function diff(oldTree, newTree) {
  3.     var patchs = {};  // 伪数组,记录差异
  4.     //  对4种节点做错判断
  5.     dfWork(oldTree, newTree, patchs, index)
  6.     return patchs
  7. }
  8. function dfWork(oldTree, newTree, patchs, index) {
  9.     let currentPatch = []
  10.     if (1) { // 对节点的删除
  11.         currentPatch.push()
  12.     } else if (3) { // 对节点的文本的更换
  13.         currentPatch.push()
  14.     } else { // 修改节点的props 对children的检查
  15.         // 对props作diff算法,把变化记录到patchs中。
  16.         currentPatch.push({ type: patch.PROPS, props: propsPatches })
  17.         // 然后需要对子节点作diff算法
  18.         diffChildren(oldNode.children, newNode.children, index, patches, currentPatch)
  19.     }
  20. }
  21. function diffChildren(oldChildren, newChildren, index, patches, currentPatch) {
  22.     // 对子节点作diff算法,遍历子节点,递归调用dfWork,做差异得到patchs
  23. }
  24. // 把变化应用在真实的DOM树上
  25. function patch(node, patchs) {
  26.     // node为老的DOM树,patchs变化。
  27.     // 我们会遍历这个patchs,并且把node和patch对应上,
  28. }
  29. function applyPatch(node, patchs) {
  30.     // 应为每个节点可能有多个变化,所以也需要遍历
  31.     switch (patchs.type) {
  32.         case REPLACE: // 节点替换
  33.             // node.render()
  34.             break;
  35.         case REORDER:  // 节点的移动删除新增子节点。
  36.             break;
  37.         case PROPS:
  38.             // setProps
  39.             break;
  40.         case TEXT: // 对节点文本的修改
  41.             // node.nodeValue
  42.             break;
  43.         default:
  44.             break;
  45.     }
  46. }
复制代码
参考文档:深度剖析:如何实现一个 Virtual DOM 算法 作者:livoras,内置源码。
到此这篇关于react中的假造dom和diff算法的文章就先容到这了,更多相关react假造dom和diff算法内容请搜刮草根技能分享以前的文章或继续欣赏下面的相关文章盼望各人以后多多支持草根技能分享!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作