vue源码之抽象dom树
一、抽象DOM树
使用过vue的朋友应该都知道,vue使用的是虚拟DOM,将DOM抽象成一个以JavaScript对象为节点的虚拟DOM树,以VNode节点模拟真实DOM,可以对这颗抽象树进行创建节点、删除节点以及修改节点等操作,在这过程中都不需要操作真实DOM,只需要操作JavaScript对象后只对差异修改。修改以后经过diff算法得出一些需要修改的最小单位,再将这些小单位的视图进行更新。这样做减少了很多不需要的DOM操作,大大提高了性能。
二、VNode节点及方法
源码位置:src/core/vdom/vnode.js
/* @flow */
export default class VNode {
tag: string | void;
data: VNodeData | void;
children: ?Array<VNode>;
text: string | void;
elm: Node | void;
ns: string | void;
context: Component | void; // rendered in this component's scope
key: string | number | void;
componentOptions: VNodeComponentOptions | void;
componentInstance: Component | void; // component instance
parent: VNode | void; // component placeholder node
// strictly internal
raw: boolean; // contains raw HTML? (server only)
isStatic: boolean; // hoisted static node
isRootInsert: boolean; // necessary for enter transition check
isComment: boolean; // empty comment placeholder?
isCloned: boolean; // is a cloned node?
isOnce: boolean; // is a v-once node?
asyncFactory: Function | void; // async component factory function
asyncMeta: Object | void;
isAsyncPlaceholder: boolean;
ssrContext: Object | void;
fnContext: Component | void; // real context vm for functional nodes
fnOptions: ?ComponentOptions; // for SSR caching
fnScopeId: ?string; // functional scope id support
constructor (
tag?: string,
data?: VNodeData,
children?: ?Array<VNode>,
text?: string,
elm?: Node,
context?: Component,
componentOptions?: VNodeComponentOptions,
asyncFactory?: Function
) {
this.tag = tag
this.data = data
this.children = children
this.text = text
this.elm = elm
this.ns = undefined
this.context = context
this.fnContext = undefined
this.fnOptions = undefined
this.fnScopeId = undefined
this.key = data && data.key
this.componentOptions = componentOptions
this.componentInstance = undefined
this.parent = undefined
this.raw = false
this.isStatic = false
this.isRootInsert = true
this.isComment = false
this.isCloned = false
this.isOnce = false
this.asyncFactory = asyncFactory
this.asyncMeta = undefined
this.isAsyncPlaceholder = false
}
// DEPRECATED: alias for componentInstance for backwards compat.
/* istanbul ignore next */
get child (): Component | void {
return this.componentInstance
}
}
//创建一个虚拟节点
export const createEmptyVNode = (text: string = '') => {
const node = new VNode()
node.text = text
node.isComment = true
return node
}
//创建一个文本节点
export function createTextVNode (val: string | number) {
return new VNode(undefined, undefined, undefined, String(val))
}
//克隆一个节点
// optimized shallow clone
// used for static nodes and slot nodes because they may be reused across
// multiple renders, cloning them avoids errors when DOM manipulations rely
// on their elm reference.
export function cloneVNode (vnode: VNode): VNode {
const cloned = new VNode(
vnode.tag,
vnode.data,
vnode.children,
vnode.text,
vnode.elm,
vnode.context,
vnode.componentOptions,
vnode.asyncFactory
)
cloned.ns = vnode.ns
cloned.isStatic = vnode.isStatic
cloned.key = vnode.key
cloned.isComment = vnode.isComment
cloned.fnContext = vnode.fnContext
cloned.fnOptions = vnode.fnOptions
cloned.fnScopeId = vnode.fnScopeId
cloned.asyncMeta = vnode.asyncMeta
cloned.isCloned = true
return cloned
}
比如渲染之后的dom为:
<div class="node-1">
<span class="demo">hello world</span>
</div>
对应的vnode应该是这样:
{
tag: 'div'
data: {
class: 'node-1'
},
children: [
{
tag: 'span',
data: {
class: 'demo'
}
text: 'hello world'
}
]
}
createElement用来创建一个虚拟节点。当data上已经绑定__ob__的时候,代表该对象已经被Oberver过了,所以创建一个空节点。tag不存在的时候同样创建一个空节点。当tag不是一个String类型的时候代表tag是一个组件的构造类,直接用new VNode创建。当tag是String类型的时候,如果是保留标签,则用new VNode创建一个VNode实例,如果在vm的option的components找得到该tag,代表这是一个组件,否则统一用new VNode创建。
参考:抽象DOM树
vue源码之抽象dom树的更多相关文章
- Vue源码探究-虚拟DOM的渲染
Vue源码探究-虚拟DOM的渲染 在虚拟节点的实现一篇中,除了知道了 VNode 类的实现之外,还简要地整理了一下DOM渲染的路径.在这一篇中,主要来分析一下两条路径的具体实现代码. 按照创建 Vue ...
- Vue源码探究-状态初始化
Vue源码探究-状态初始化 Vue源码探究-源码文件组织 Vue源码探究-虚拟DOM的渲染 本篇代码位于vue/src/core/instance/state.js 继续随着核心类的初始化展开探索其他 ...
- 大白话Vue源码系列(02):编译器初探
阅读目录 编译器代码藏在哪 Vue.prototype.$mount 构建 AST 的一般过程 Vue 构建的 AST 题接上文,上回书说到,Vue 的编译器模块相对独立且简单,那咱们就从这块入手,先 ...
- 大白话Vue源码系列(03):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
- 大白话Vue源码系列(04):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
- 【一套代码小程序&Native&Web阶段总结篇】可以这样阅读Vue源码
前言 前面我们对微信小程序进行了研究:[微信小程序项目实践总结]30分钟从陌生到熟悉 在实际代码过程中我们发现,我们可能又要做H5站又要做小程序同时还要做个APP,这里会造成很大的资源浪费,如果设定一 ...
- vue源码逐行注释分析+40多m的vue源码程序流程图思维导图 (diff部分待后续更新)
vue源码业余时间差不多看了一年,以前在网上找帖子,发现很多帖子很零散,都是一部分一部分说,断章的很多,所以自己下定决定一行行看,经过自己坚持与努力,现在基本看完了,差ddf那部分,因为考虑到自己要换 ...
- Vue源码分析(二) : Vue实例挂载
Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...
- Vue源码详细解析:transclude,compile,link,依赖,批处理...一网打尽,全解析!
用了Vue很久了,最近决定系统性的看看Vue的源码,相信看源码的同学不在少数,但是看的时候却发现挺有难度,Vue虽然足够精简,但是怎么说现在也有10k行的代码量了,深入进去逐行查看的时候感觉内容庞杂并 ...
随机推荐
- SRM474
250pt 题意:在一个N维的空间里,有一个人开始在原点,现在给出N<=50个指令序列,每个指令序列为某一维+1或者减一,问是否经过某个点至少2次. 思路:操作很小,直接模拟判断即可 code: ...
- TTL与CMOS门电路
个人观点总结 对TTL和CMOS门电路的认识: 1.构成 TTL集成电路一般都是有三极管(或二极管)和电阻.电容构成,其中三极管(二极管)是作为主要的开关器件 CMOS集成电路一般是由场效应管和电阻. ...
- asp.net core mvc 中间件之WebpackDevMiddleware
asp.net core mvc 中间件之WebpackDevMiddleware WebpackDevMiddleware中间件主要用于开发SPA应用,启用Webpack,增强网页开发体验.好吧,你 ...
- ASP 基础一
ASP是什么? •ASP代表Active Server Pages(动态服务器页面) •需在IIS中运行的程序 我自己的理解就是UI和逻辑代码同在一个页面中,而缺点就是不易维护.code-Behind ...
- ASP.NET MVC5 高级编程-学习日记-第一章 入门
1.1 ASP.NET MVC 简介 ASP.NET是一种构建Web应用程序的框架,它将一般的MVC(Model-View-Controller)模式应用于ASP.NET框架. 1.1.1 MVC模式 ...
- 使用 xUnit 编写 ASP.NET Core WebAPI单元测试
本文使用xUnit对ASP.NET Core WebAPI做单元测试,使用HttpClient的同步和异步请求,下面详细介绍xUnit的使用过程: 一.创建示例项目 模板为我们自动创建了一个Value ...
- 二进制转化为十进制Java实现
二进制转化为十进制 ①按权展开方法Java实现 /* * 按权展开法 */ public static double BinToTen1(String binary) { //查找该二进制是否存在小数 ...
- 值不能为 null。 参数名: source
今天调试程序总是报一个异常: 值不能为 null.参数名: source 异常详细信息: System.ArgumentNullException: 值不能为 null.参数名: source 通过断 ...
- Git 本地操作
版权声明:数学是研究世界的本质,自然科学是研究上帝的意志,而计算机则是揣摩屌丝人类的意志 目录(?)[-] 命令 git config 增删改查 init clone add commit sta ...
- oracle 11g RAC数据库监听配置相关
oracle RAC 监听配置基本和单实例的配置相同 11g之后 安装RAC的过程中,不需要执行netca来手动创建监听,在安装集群软件的时候,会自动创建监听程序: 而在DBCA建库的时候,又会自动创 ...