Vue.js 是一个 MVVM 框架结构。 它的特点是核心聚焦于视口elementui文本标签,而虚拟节点(以下简称VNode)是这个核心的重要支柱(另一个支柱我认为是用来实现响应式框架的Watcher)
1、首先看VNode的类定义:
/** * tag - 标签类型,例如 p、div * data - 标签上的数据,例如 style、class、data-* * children - 顾名思义,子节点 * text - 文本内容 * elm - 虚拟节点绑定的真实 DOM 节点 * context - 一般是 Vue 实例 * componentOptions - 父组件传给子组件的属性 */ var VNode = function VNode(tag, data, children, text, elm, context, componentOptions, asyncFactory) { this.tag = tag; this.data = data; this.children = children; this.text = text; this.elm = elm; this.ns = undefined; this.context = context; this.key = data && data.key; this.parent = undefined; this.raw = false; this.componentOptions = componentOptions; // ... 还有些属性我就不列出来了,大家可以自行去看源码 };
接下来我们看一下VNode是如何解释节点的:用简单的节点
你好
例如,它将被解释为 2 个 VNode。 一种是标签类型为p但没有文本值的节点,下面简称为标签节点; 另一种是没有标签类型、有文本值的节点,下面简称文本节点。
我们来了解一下VNode的解析过程,看下面的代码
Hello world
日期:2017-11-9
时间戳:1510196747299
不妨先考虑一下这个页面结构会被分割成多少个节点,然后再看下面每个VNode的创建顺序:
文本节点 Helloworld 标签节点 h1 文本节点日期:2017-11-9 标签节点 p#text1 文本节点时间戳:1510196747299 标签节点 p#text2 标签节点 div#wrap 标签节点 div#app
从前面的列表中elementui文本标签,我们可以看到Vue从上到下、从内到外解析节点。 那么当页面结构组件丰富时会如何解析呢? 我就不写例子了,直接给你结果:Vue会先解析主文档,然后解析组件,组件在父文档中的位置就是组件解析后的挂载点。
2. 问答
1.Q:为什么VNode的解析顺序是自上而下,从内到外?
A:因为你写的HTML经过parseHTML时,会形成类似下面的函数。
/** * _s = toString 方法 * _v = 创建文本节点 * _c = 创建标签节点 */ function f() { with (this) { return _c( 'div', { attrs: { "id": "app" } }, [ _ c( 'h1', { staticClass: "h1", staticStyle: { "color": "red" }, attrs: { "data-id": "1" } }, [_v(_s(message))] ) ] ) } }
完全符合JS的解析顺序。 同时这个方法会被缓存。 上次有节点更新时直接调用即可,一定程度上提高了页面渲染的性能。
2.Q:v-on、v-bind等指令何时绑定节点上?
A:在parseHTML流程的processAttrs方法中