作为React的核心技术之一Virtual DOM,一直披着神秘的面纱。

实际上,Virtual DOM包含:

  1. Javascript DOM模型树(VTree),类似文档节点树(DOM)
  2. DOM模型树转节点树方法(VTree -> DOM)
  3. 两个DOM模型树的差异算法(diff(VTree, VTree) -> PatchObject)
  4. 根据差异操作节点方法(patch(DOMNode, PatchObject) -> DOMNode)

接下来我们分别探讨这几个部分:

VTree

VTree模型非常简单,基本结构如下:

{
// tag的名字
tagName: 'p',
// 节点包含属性
properties: {
style: {
color: '#fff'
}
},
// 子节点
children: [],
// 该节点的唯一表示,后面会讲有啥用
key: 1
}

所以我们很容易写一个方法来创建这种树状结构,例如React是这么创建的:

// 创建一个div
react.createElement('div', null, [
// 子节点img
react.createElement('img', { src: "avatar.png", class: "profile" }),
// 子节点h3
react.createElement('h3', null, [[user.firstName, user.lastName].join(' ')])
]);

VTree -> DOM

这方法也不太难,我们实现一个简单的:

function create(vds, parent) {
// 首先看看是不是数组,如果不是数组统一成数组
!Array.isArray(vds) && (vds = [vds]);
// 如果没有父元素则创建个fragment来当父元素
parent = parent || document.createDocumentFragment();
var node;
// 遍历所有VNode
vds.forEach(function (vd) {
// 如果VNode是文字节点
if (isText(vd)) {
// 创建文字节点
node = document.createTextNode(vd.text);
// 否则是元素
} else {
// 创建元素
node = document.createElement(vd.tag);
}
// 将元素塞入父容器
parent.appendChild(node);
// 看看有没有子VNode,有孩子则处理孩子VNode
vd.children && vd.children.length &&
create(vd.children, node); // 看看有没有属性,有则处理属性
vd.properties &&
setProps({ style: {} }, vd.properties, node);
});
return parent;
}

diff(VTree, VTree) -> PatchObject

差异算法是Virtual DOM的核心,实际上该差异算法是个取巧算法(当然你不能指望用O(n^3)的复杂度来解决两个树的差异问题吧),不过能解决Web的大部分问题。

那么React是如何取巧的呢?

  1. 分层对比

如图,React仅仅对同一层的节点尝试匹配,因为实际上,Web中不太可能把一个Component在不同层中移动。

  1. 基于key来匹配

还记得之前在VTree中的属性有一个叫key的东东么?这个是一个VNode的唯一识别,用于对两个不同的VTree中的VNode做匹配的。

这也很好理解,因为我们经常会在Web遇到拥有唯一识别的Component(例如课程卡片、用户卡片等等)的不同排列问题。

  1. 基于自定义元素做优化

React提供自定义元素,所以匹配更加简单。

patch(DOMNode, PatchObject) -> DOMNode

由于diff操作已经找出两个VTree不同的地方,只要根据计算出来的结果,我们就可以对DOM的进行差异渲染。

扩展阅读

具体可参考下面两份代码实现:

  1. @Matt-Esch实现的:virtual-dom
  2. 我们自己做的简版实现,用于Mobile页面渲染的:qvd

前沿技术解密——VirtualDOM的更多相关文章

  1. 一个周末掌握IT前沿技术之node.js篇

    一个周末掌握IT前沿技术之node.js篇 http://ittechnical.sinaapp.com/node-js-and-restful-api/ NodeJS入门  http://www.n ...

  2. MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件

    原文  MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件 UI 前沿技术 WPF 中的多点触控操作事件 Charles Petzold 下载代码示例 就在过去几年,多点触控还只是科幻电 ...

  3. Android NFC开发(一)——初探NFC,了解当前前沿技术

    Android NFC开发(一)--初探NFC,了解当前前沿技术 官方文档:http://developer.android.com/guide/topics/connectivity/nfc/ind ...

  4. MOT大连站 | 卓越研发之路:前沿技术落地实践

    还在讨论究竟哪种编程语言更容易深度学习?哪种编程语言更具有价值?如果你是资深技术人员又或者是团队负责人,在机器学习.微服务.Spring 5反应式编程等方面遇到了问题,不妨参加一场由msup和微软联合 ...

  5. 爆款AR游戏如何打造?网易杨鹏以《悠梦》为例详解前沿技术

    本文来自网易云社区. 7月31日,2018云创大会游戏论坛在杭州国际博览中心103B圆满举行.本场游戏论坛聚焦探讨了可能对游戏行业发展有重大推动的新技术.新实践,如AR.区块链.安全.大数据等. 网易 ...

  6. 为数据赋能:腾讯TDSQL分布式金融级数据库前沿技术

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 简介:李海翔,网名"那海蓝蓝",腾讯金融云数据库技术专家.中国人民大学信息学院工程硕士企业导师.著有<数据库事务处 ...

  7. vivo营销自动化技术解密|开篇

    一.营销自动化概览 1.1. 什么是营销自动化 营销自动化是指专门为营销部门或组织设计的软件平台和技术,可以更有效地在线进行多渠道营销并使重复性任务自动化.营销部门和销售人员通过制定任务和流程的操作标 ...

  8. 宜人贷蜂巢API网关技术解密之Netty使用实践

    一.背景 宜人贷蜂巢团队,由Michael创立于2013年,通过使用互联网科技手段助力金融生态和谐健康发展.自成立起一直致力于多维度数据闭环平台建设.目前团队规模超过百人,涵盖征信.电商.金融.社交. ...

  9. Android前沿技术

    一.热升级Tinker源码解析与手写二.热修复阿里百川Sophix内核原理三.App Instantgoogle8.0 类似热更新技术原理与实战四.强制更新1.银行应用非对称加密对称加密五.组件化框架 ...

随机推荐

  1. Divide Two Integers leetcode

    题目:Divide Two Integers Divide two integers without using multiplication, division and mod operator. ...

  2. 5.2 Adapter

    1 ArrayAdapter 只可以简单的显示一行文本 ArrayAdapter<String> adapter = new ArrayAdapter<String>( thi ...

  3. iOS开发零基础--Swift篇:Swift中数据类型

    Swift类型的介绍 Swift中的数据类型也有:整型/浮点型/对象类型/结构体类型等等 先了解整型和浮点型 整型 有符号 Int8 : 有符号8位整型 Int16 : 有符号16位整型 Int32 ...

  4. php笔试题(2)--转载

    1.用PHP打印出前一天的时间格式是2006-5-10   22:21:212.echo(),print(),print_r()的区别3.能够使HTML和PHP分离开使用的模板4.如何实现PHP.JS ...

  5. 01背包问题:Charm Bracelet (POJ 3624)(外加一个常数的优化)

    Charm Bracelet    POJ 3624 就是一道典型的01背包问题: #include<iostream> #include<stdio.h> #include& ...

  6. C#设计模式(20)——策略者模式(Stragety Pattern)

    一.引言 前面主题介绍的状态模式是对某个对象状态的抽象,而本文要介绍的策略模式也就是对策略进行抽象,策略的意思就是方法,所以也就是对方法的抽象,下面具体分享下我对策略模式的理解. 二.策略者模式介绍 ...

  7. UML建模语言入门 -- 用例视图详解 用例视图建模实战

    . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 一. 用例视图概述 用例视图表述哪些 ...

  8. GCC选项

    -g: Debugging Option. 提供给GDB的debugging信息的选项: -fno-omit-frame-pointer: Optimization Option: -Wstrict- ...

  9. atitit.人脸识别的应用场景and使用最佳实践 java .net php

    atitit.人脸识别的应用场景and使用最佳实践 java .net php 1. 人脸识别的应用场景 1 2. 框架选型 JNI2OpenCV.dll and JavaCV 1 3. Url ap ...

  10. atitit.架构设计---方法调用结果使用异常还是返回值

    atitit.架构设计---方法调用结果使用异常还是返回值 1. 应该返回BOOL类型还是异常 1 2. 最终会有四种状况,抛出异常.返回特殊值.阻塞.超时 1 3. 异常的优缺点点 1 4. jav ...