DOM操作是昂贵的,为了减少DOM操作,才有了Virtual DOM。而Virtual DOM的关键就是通过对比新旧vnode,找出差异部分来更新节点。对比的关键算法就是Diff算法。

历史由来:

diff算法历史悠久,并不是虚拟dom提出来的。早在linux系统中,就有diff命令,用于比较两个文本的差异,还有一个最常用的就是git diff命令,由于比较两个版本之间的差异。Virtual DOM的算法是用来对比新旧虚拟dom的差异。

核心逻辑:

1. creatElement

首先先来分析patch函数的第一种用法:patch(container, vnode).。如何把虚拟dom转化成真正的DOM?

假设每个节点都包含tag,props,children三个属性(按最简单的情况考虑)

step 1: 创建节点;

step 2: 设置属性;

step 3; 遍历子节点,子节点也需要结果step1,2,然后加到当前节点中。

经过分析,我们发现创键DOM,需要用到递归。

代码模拟如下:

function createElement(vnode) {
var tag = vnode.tag;//获取元素的标签
var props = vnode.props || {};//获取元素的属性
var children = vnode.children || [];//获取子节点 if (!tag) {
return null;
} var ele = document.createElement(tag);//step1:创建元素
// step2:设置属性
var attrName;
for (attrName in props) {
if (props.hasOwnProperty(attrName)) {
ele.setAttribute(attrName, props[attrName])
}
}
//step3:深度遍历子元素,并插入当前节点
children.forEach(element => {
ele.appendChild(createElement(element)); //递归调用
});
return ele;
}

2. updateChild

接着再来分析一下patch函数的第二种用法:patch(oldVnode, newVnode)。如何找出新旧节点的差异,并更新节点?

假设只考虑最简单的情况,只改变以下<li>标签的值。

function updateChild(vnode,newVnode) {
var oldchild = vnode.children || [];
var newchild = newVnode.children || []; oldchild.forEach(function (childItem, index) {
var newChildItem = newchild[index]; //假设层级相同
if(newChildItem.tag === childItem.tag) {
updateChild(childItem, newChildItem) //如果相同则递归遍历
} else {
replaceNode(childItem, newChildItem)//否则替换dom
}
})
}
function replaceNode(parantNode, oldchildNode, newChildNode) {
var oldelem = oldchildNode.elem; //获取真实dom
var newElem = newChildNode.elem;
//替换dom
parantNode.replaceChild(newElem,oldelem);
}

注:以上代码都是伪代码,只考虑了最简单的情况。

总结:

实际diff算法非常复杂,还需考虑节点的新增,删除;节点的重新排序;节点属性、样式、事件的绑定等。

1. virtual dom是什么?为何使用VD?

虚拟DOM

用JS模拟DOM结构

DOM操作非常昂贵

将DOM对比放在JS层,提高效率

2. 核心API

h('<html 标签名>',{属性},[children])//含有子节点的

h('<html 标签名>',{属性},'text'])//没有子节点,只有文本,如<p>this is VN</p>

patch(container, vnode)//初次渲染

patch(oldVnode, newVnode); //re-render

3. diff算法

creatElement,updateChild逻辑

Virtual DOM 系列三:Diff算法的更多相关文章

  1. Virtual DOM 系列二:核心API

    为了更好的研究Virtual DOM,我选择了snabbdom来学习.相比Vue来说,snabbdom对于研究虚拟DOM更好,因为它里面没有其他干扰的东西,而且源码也比较少,因此研究起来更方便. 1. ...

  2. Virtual DOM 系列一:认识虚拟DOM

    1. 什么是Virtual DOM? Virtual DOM(虚拟DOM)是指用JS模拟DOM结构.本质上来讲VD是一个JS对象,并且至少包含三个属性:tag(html标签),props(标签的属性, ...

  3. React之虚拟DOM中的Diff算法

    一.React中的setState ( 异步函数,异步获取数据 ) 若操作的时间间隔短,它可以将多个setState结合成一个setState,减少虚拟DOM的比对次数,提高性能 二.同层虚拟DOM对 ...

  4. jvm系列(三):GC算法 垃圾收集器

    原文出处:纯洁的微笑 这篇文件将给大家介绍GC都有哪几种算法,以及JVM都有那些垃圾回收器,它们的工作原理. 概述 垃圾收集 Garbage Collection 通常被称为"GC" ...

  5. 一篇文章教会你如何将DOM转换为virtual DOM

    [一.Virtual DOM简介] Virtual DOM是虚拟节点,它通过Javascript的Object对象模拟DOM中的节点,然后通过特定的render方法将其渲染成真实的DOM节点. 浏览器 ...

  6. diff算法深入一下?

    文章转自豆皮范儿-diff算法深入一下 一.前言 有同学问:能否详细说一下 diff 算法. 简单说:diff 算法是一种优化手段,将前后两个模块进行差异化比较,修补(更新)差异的过程叫做 patch ...

  7. 从 0 到 1 实现 React 系列 —— 3.生命周期和 diff 算法

    看源码一个痛处是会陷进理不顺主干的困局中,本系列文章在实现一个 (x)react 的同时理顺 React 框架的主干内容(JSX/虚拟DOM/组件/生命周期/diff算法/setState/ref/. ...

  8. 深入理解react中的虚拟DOM、diff算法

    文章结构: React中的虚拟DOM是什么? 虚拟DOM的简单实现(diff算法) 虚拟DOM的内部工作原理 React中的虚拟DOM与Vue中的虚拟DOM比较 React中的虚拟DOM是什么?   ...

  9. react虚拟dom diff算法

    react虚拟dom:依据diff算法 前端:更新状态.更新视图:所以前端页面的性能问题主要是由Dom操作引起的,解放Dom操作复杂性 刻不容缓 因为:Dom渲染慢,而JS解析编译相对非常非常非常快! ...

随机推荐

  1. JavaScript夯实基础系列(四):原型

      在JavaScript中有六种数据类型:number.string.boolean.null.undefined以及对象,ES6加入了一种新的数据类型symbol.其中对象称为引用类型,其他数据类 ...

  2. RDIFramework.NET V3.3 Web框架主界面新增横向菜单功能

    功能描述 响应重多客户的要求与心声,RDIFramework.NET框架Web版本主界面新增横向菜单功能.横向菜单更加直观,用户可操作与展示的空间更多,符合实际应用要求. 一.效果展示 最终界面效果: ...

  3. Data Lake Analytics + OSS数据文件格式处理大全

    0. 前言 Data Lake Analytics是Serverless化的云上交互式查询分析服务.用户可以使用标准的SQL语句,对存储在OSS.TableStore上的数据无需移动,直接进行查询分析 ...

  4. 基于Socket通讯(C#)和WebSocket协议(net)编写的两种聊天功能(文末附源码下载地址)

    今天我们来盘一盘Socket通讯和WebSocket协议在即时通讯的小应用——聊天. 理论大家估计都知道得差不多了,小编也通过查阅各种资料对理论知识进行了充电,发现好多demo似懂非懂,拷贝回来又运行 ...

  5. Js-函数式编程

    前言 JavaScript是一门多范式语言,即可使用OOP(面向对象),也可以使用FP(函数式),由于笔者最近在学习React相关的技术栈,想进一步深入了解其思想,所以学习了一些FP相关的知识点,本文 ...

  6. 80后程序员降薪6K,预感中年危机来袭,准备跳槽却碰壁

    一提及程序员,很多人想到的都是“工资高”“技术好”诸如此类的,可见程序员是个非常赚钱的职业,所以每年都会有很多毕业生来选择这个行业. 但是社会是公平的,不要只看程序员表面上的光鲜亮丽,其背后也有很多的 ...

  7. vue鼠标悬停事件

    v-bind:title="message" <!DOCTYPE html> <html lang="en"> <head> ...

  8. 微信公众号签名错误 invalid signature

    在出现了 invalid signature签名错误后按照以下步骤进行校验1.确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=j ...

  9. 《JavaScript高级程序设计》笔记:使用Canvas绘图(15)

    基本用法 要使用<canvas>元素,必须先设置其width和height属性,指定可以绘图的区域大小.出现在开始和结束标签中的内容是后备信息,如果浏览器不支持<canvas> ...

  10. 五一出门必备的手机APP神器 让你瞬间大开眼界

    如今我们手机上有各种各样的软件,但是比较实用的又有哪些呢?所以每次大家都会花上很久的时间去查找满意的软件吧!今天就给大家送上一波福利,因为五一小长假就要到来了,说不定大家会使用到呢! 轻颜相机 轻颜相 ...