作为
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.银行应用非对称加密对称加密五.组件化框架 ...
随机推荐
-
hibernate-cache
hibernate缓存分:一级缓存.二级缓存.三级缓存 一级缓存:Session内的缓存 实例: /*一级缓存: * session内的缓存 * */ @Test public void test1( ...
-
SQL Server 用表中已有数据造数据
从表中选择数据再插入到表中(select XXX into 与insert into XXX select的结合) 在做性能测试时需要大量的业务数据.完全从画面造数据比较费时间,使用SQL文批量插入数 ...
-
Spark IDEA开发环境构建
本文档基于IEDA构建spark maven应用. date: 2016/8/1 author: wangxl 1.下载IDEA https://www.jetbrains.com/idea/ 2.安 ...
-
MySQL数据备份之mysqldump使用(转)
mysqldump常用于MySQL数据库逻辑备份. 1.各种用法说明 A. 最简单的用法: mysqldump -uroot -pPassword [database name] > [dump ...
-
Codeforces 809E Surprise me! [莫比乌斯反演]
洛谷 Codeforces 非常套路的一道题,很适合我在陷入低谷时提升信心-- 思路 显然我们需要大力推式子. 设\(p_{a_i}=i\),则有 \[ \begin{align*} n(n-1)an ...
-
父级div宽度100%,子级一个div宽度固定,另一个宽度自适应
<!DOCTYPE html> <html> <head> <title>布局测试</title> <style type=" ...
-
dasd
https://www.crifan.com/use_pyinstaller_to_package_python_to_single_executable_exe/ http://blog.csdn. ...
-
BZOJ5251 八省联考2018劈配(网络流)
劈配,匹配,网络流.那么考虑怎么跑网络流. 先看第一问.首先套路的建出超源超汇.不用想也知道导师向汇连容量为战队人数上限的边.特别地,给出局也建一个点,向汇连容量inf的边(似乎没有必要).对于一个新 ...
-
再论hibernatetemplate
自动生成hibernate配置文件的时候,会在dao层用到getSession()方法来操作数据库记录,但是他还有个方法getHibernateTemplate(),这两个方法究竟有什么区别呢? 1. ...
-
centos 7 nginx 安装
1.下载nginx rpm包 下载地址:http://nginx.org/packages/mainline/centos/7/x86_64/RPMS/ ,可查看所有安装包 从中如下载: wget h ...