美文网首页
Vue.js之虚拟节点VNode

Vue.js之虚拟节点VNode

作者: KimYYX | 来源:发表于2017-11-09 15:38 被阅读0次

众所周知,Vue.jsMVVM 框架结构,其特色在于核心重点关注视图层,而虚拟节点(以下简称 VNode)是这一核心的重要支柱(另一根支柱我觉得是实现响应式框架用到的 Watcher)。下面我们稍微深挖一下 VNode 的“背景”。


一、初识

首先看下 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 纯粹是对 View 层的映射,仅有属性,没有方法。

接着看下 VNode 对节点的解释方式:以简单节点 <p>Hello</p> 为例,其会被解释成2个 VNode 的。一个是 tag 类型为 p ,但没有 text 值的节点,下文称为标签节点;另一个是没有 tag 类型,但是有 text 值的节点,下文称为文本节点

再来了解下 VNode解析流程,看下面的代码

<div id="app">
  <h1 class="h1" style="color:red;" data-id="1">Hello world</h1>
  <div id="wrap">
    <p id="text1">日期:2017-11-9</p>
    <p id="text2">时间戳:1510196747299</p>
  </div>
</div>

大家不妨可以先考虑下,这个页面结构会被拆成多少个节点,再来看下面各个 VNode 的创建顺序:

  1. 文本节点 Hello world
  2. 标签节点 h1
  3. 文本节点 日期:2017-11-9
  4. 标签节点 p#text1
  5. 文本节点 时间戳:1510196747299
  6. 标签节点 p#text2
  7. 标签节点 div#wrap
  8. 标签节点 div#app

从上面的列表可以看出 Vue 对节点的解析是自上而下,从内到外解析的。那么当页面结构中含有 component 会如何解析呢?样例我就不写了,直接给个结果:Vue 会先解析主文档,然后解析组件,而父文档中的组件位置就是组件解析完之后的挂载点。


二、Q & A

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-onv-bind 等指令是什么时候绑定的

A:parseHTML 过程的 processAttrs 方法中


三、阅读源码后的一点感想

  1. 需要比较扎实的正则能力,parseHTML 中的元素剥离就是靠的正则
  2. 了解ES2015的新API,例如 proxydefineProperty 等,这也是 Vue 不支持旧版浏览器的原因
  3. 闭包知识,常常一个方法被包了3层之多
  4. 1万多行的代码里面,好多都是常量定义和具方法,如果剥离出来,可能会更方便阅读

相关文章

  • Vue.js之虚拟节点VNode

    众所周知,Vue.js 是 MVVM 框架结构,其特色在于核心重点关注视图层,而虚拟节点(以下简称 VNode)是...

  • 2021-03-06 虚拟dom - 01

    入口文件 h方法的实现 (创建虚拟节点) 创建虚拟节点 vnode.js patch (render) 将虚拟节点...

  • 实现 Virtual DOM

    什么是 VNode 我们知道,render function 会被转化成 VNode 节点。虚拟 DOM (Vir...

  • v-for中的key的作用(二)

    一. VNode div,body等标签渲染到浏览器中的是真实节点VNode,虚拟节点,存在于内存中的JavaSc...

  • vue 虚拟dom

    vnode => dom虚拟 => 真是dom (vue 初始化渲染) 更新节点

  • Vue虚拟Dom

    虚拟dom:vdom是树状结构,其节点为vnode,vnode和浏览器DOM中的Node一一对应,通过vnode的...

  • 面试题目整理

    vue相关 1.VNode是什么?什么是虚拟dom? 在vue.js中存在一个VNode类,使用它可以实例化不同类...

  • 理解vue2.x之diff算法

    了解diff算法前,应该先了解虚拟DOM(VNode),在vue中是先创建VNode,再通过diff算法看哪个节点...

  • 虚拟dom和diff算法

    一、什么是虚拟dom 虚拟DOM 其实就是一棵以 JavaScript 对象 (VNode 节点) 作为基础的树,...

  • 两种方法实现vue的虚拟DOM

    虚拟DOM的优势 首先是可以对真实的元素节点进行抽象,抽象成VNode(虚拟节点),这样方便后续对其进行各种操作因...

网友评论

      本文标题:Vue.js之虚拟节点VNode

      本文链接:https://www.haomeiwen.com/subject/inkpmxtx.html