前沿技术解密——VirtualDOM
作为
React的核心技术之一Virtual DOM,一直披着神秘的面纱。
实际上,Virtual DOM包含:
- Javascript DOM模型树(VTree),类似文档节点树(DOM)
 - DOM模型树转节点树方法(VTree -> DOM)
 - 两个DOM模型树的差异算法(diff(VTree, VTree) -> PatchObject)
 - 根据差异操作节点方法(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是如何取巧的呢?
- 分层对比
 
如图,React仅仅对同一层的节点尝试匹配,因为实际上,Web中不太可能把一个Component在不同层中移动。
- 基于key来匹配
 
还记得之前在VTree中的属性有一个叫key的东东么?这个是一个VNode的唯一识别,用于对两个不同的VTree中的VNode做匹配的。
这也很好理解,因为我们经常会在Web遇到拥有唯一识别的Component(例如课程卡片、用户卡片等等)的不同排列问题。
- 基于自定义元素做优化
 
React提供自定义元素,所以匹配更加简单。
patch(DOMNode, PatchObject) -> DOMNode
由于diff操作已经找出两个VTree不同的地方,只要根据计算出来的结果,我们就可以对DOM的进行差异渲染。
扩展阅读
具体可参考下面两份代码实现:
- @Matt-Esch实现的:virtual-dom
 - 我们自己做的简版实现,用于Mobile页面渲染的:qvd
 
前沿技术解密——VirtualDOM的更多相关文章
- 一个周末掌握IT前沿技术之node.js篇
		
一个周末掌握IT前沿技术之node.js篇 http://ittechnical.sinaapp.com/node-js-and-restful-api/ NodeJS入门 http://www.n ...
 - MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件
		
原文 MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件 UI 前沿技术 WPF 中的多点触控操作事件 Charles Petzold 下载代码示例 就在过去几年,多点触控还只是科幻电 ...
 - Android NFC开发(一)——初探NFC,了解当前前沿技术
		
Android NFC开发(一)--初探NFC,了解当前前沿技术 官方文档:http://developer.android.com/guide/topics/connectivity/nfc/ind ...
 - MOT大连站 | 卓越研发之路:前沿技术落地实践
		
还在讨论究竟哪种编程语言更容易深度学习?哪种编程语言更具有价值?如果你是资深技术人员又或者是团队负责人,在机器学习.微服务.Spring 5反应式编程等方面遇到了问题,不妨参加一场由msup和微软联合 ...
 - 爆款AR游戏如何打造?网易杨鹏以《悠梦》为例详解前沿技术
		
本文来自网易云社区. 7月31日,2018云创大会游戏论坛在杭州国际博览中心103B圆满举行.本场游戏论坛聚焦探讨了可能对游戏行业发展有重大推动的新技术.新实践,如AR.区块链.安全.大数据等. 网易 ...
 - 为数据赋能:腾讯TDSQL分布式金融级数据库前沿技术
		
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 简介:李海翔,网名"那海蓝蓝",腾讯金融云数据库技术专家.中国人民大学信息学院工程硕士企业导师.著有<数据库事务处 ...
 - vivo营销自动化技术解密|开篇
		
一.营销自动化概览 1.1. 什么是营销自动化 营销自动化是指专门为营销部门或组织设计的软件平台和技术,可以更有效地在线进行多渠道营销并使重复性任务自动化.营销部门和销售人员通过制定任务和流程的操作标 ...
 - 宜人贷蜂巢API网关技术解密之Netty使用实践
		
一.背景 宜人贷蜂巢团队,由Michael创立于2013年,通过使用互联网科技手段助力金融生态和谐健康发展.自成立起一直致力于多维度数据闭环平台建设.目前团队规模超过百人,涵盖征信.电商.金融.社交. ...
 - Android前沿技术
		
一.热升级Tinker源码解析与手写二.热修复阿里百川Sophix内核原理三.App Instantgoogle8.0 类似热更新技术原理与实战四.强制更新1.银行应用非对称加密对称加密五.组件化框架 ...
 
随机推荐
- nodejs: C++扩展
			
Nodejs的C++扩展首先保证nodejs和v8都正确安装 下载NodeJS源码,我的放在D盘. NodeJS的C++扩展要用VS2010开发,新建一个空的Win32控制台项目,右键——属性,在常规 ...
 - Spring MVC 指导文档解读(一)
			
22.1 指导文档章节 In the Web MVC framework, each DispatcherServlet has its own WebApplicationContext, whic ...
 - 银行IT入门深似海
			
最初就是接触各种系统,了解各大系统的功能 像建行 从终端到后台就经历10多个系统 另外,就是各种标准规范 例如报文规范 搞终端我师父让我看8583规范 还有什么银联的规范 PBOC什么的 我现在还 ...
 - hdu 4651 - Partition(五边形数定理)
			
定理详见维基百科....http://zh.wikipedia.org/wiki/%E4%BA%94%E9%82%8A%E5%BD%A2%E6%95%B8%E5%AE%9A%E7%90%86 代码如下 ...
 - linux SMP启动
			
SMP简介 1,硬件上,CPU没有主次之分 2,软件上,每个CPU平等动态地从进程就绪队列中调度进程加以执行,中断请求也是等概率动态的分布给某个CPU SMP启动 1,SMP结构中的CPU都是平等的, ...
 - Zabbix3.0 自动电话报障
			
第一种:Pagerduty 网站:www.pagerduty.com 优点:老牌服务商,稳定 缺点:贵,英文,网站要FQ 价格参考(34美元每月才25个电话,*29每月是包年才有的价格) 安装方式: ...
 - [leetcode 226] Invert Tree
			
1 题目: Invert a binary tree. 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 2 思路: 这是因为谷歌面试xx而 ...
 - Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮
			
上次介绍了 Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示 现在开始介绍如何配置审批流,首先在form上添加三个按钮,Submit, Agree, Reject: 1. ...
 - Dynamic CRM 2013学习笔记(七)追踪、监控及性能优化
			
本文将介绍CRM的三个内容追踪.监控及性能优化.追踪是CRM里一个很有用的功能,它能为我们的CRM调试或解决错误.警告提供有价值的信息:我们可以用window的性能监控工具来了解CRM的性能状况:最后 ...
 - C#过滤Html标签及空格
			
public static string FilterHTML(string HTMLStr) { if (!string.IsNullOrEmpty(HTMLStr)) return System. ...