在零星碎片地学了vue中渲染流程的一些知识后,有必要对vue整个渲染流程做一次梳理,确保知识的连贯性。
vue中的渲染流程主要有下面三个阶段。
1、响应式:监听data
属性getter setter
。
2、模版编译:模版到 render
函数,再到vnode
。
3、vnode:初次渲染视图vnodepatch(elem,vnode)
和更新视图patch(vnode,newVnode)
。
首先我们来看一张图,通过这张图,我们来看一下vue中渲染流程的主要步骤。
1、执行
Component Render Function
方法,生成Virtual DOM Tree
.2、执行第一步的同时触发
data
中的getter
。3、收集依赖(Collect as Dependency)。在模板中使用了哪个变量,就把那个变量观察起来
(Watcher)
,没有用到变量,不会被收集。4、如果通过
data
中的setter
修改了data
中的数据,就需要查看一下watcher
中是否将这个变量观察起来。如果之前已经观察起来,就会触发re-render
,重新生成Component Render Function
,重新生成vdom(当然此过程会进行diff算法)。对整个流程梳理完成后,我们从每个阶段入手,逐个阶段的去理解这一渲染流程。
一、渲染流程分析
1、响应式:监听data
属性getter setter
这部分主要是对模版中用到的变量添加监听。我在文章《vue中响应式数据状态原理分析》中有过非常详细的分析以及实现,你可以点击文中链接进行学习。
2、模版编译:模版到 render
函数,再到vnode
模板不是html,有指令、插值、JS表达式,能够实现判断、循环。html是标签语言,只有JS才能实现判断、循环(图灵完备性)。因此,模版一定要转化成某种JS代码,即编译模版。模版编译为render函数,执行render函数返回vnode。
在学习这段内容的时候,要掌握with语法
,我们简单的复习一下with
的用法吧。
with 语法with 语法
1、改变{}内自由变量的查找规则,当作obj属性来查找。
2、如果找不到匹配的obj属性,就会报错。
3、with要慎用,它打破了作用域规则,易读性变差。
我们可以借助
vue-template-compiler
这个第三方库来体验一下,模版编译的过程。具体流程如下:1、安装环境
npm init -y
npm install vue-template-compiler
2、编写测试文件(index.js)
const compiler = require('vue-template-compiler')
// 插值
const template = `<p>{{message}}</p>`
// 编译
const res = compiler.compile(template)
console.log(res.render)
3、运行测试文件,获取render函数
node index.js
运行的结果如下:
with(this){return _c('p',[_v(_s(message))])}
是不是很熟悉,用到了我们前面学到的with
语法。this
就是vm
示例,const vm = new Vue({})
,_c
,就是我们熟悉的createElement
,对照vue源码定义的快捷方法,我们可以知道_v
和_s
方法的含义,即创建文本节点和调用toString
方法。
unction installRenderHelpers (target) {
target._o = markOnce;
target._n = toNumber;
target._s = toString;
target._l = renderList;
target._t = renderSlot;
target._q = looseEqual;
target._i = looseIndexOf;
target._m = renderStatic;
target._f = resolveFilter;
target._k = checkKeyCodes;
target._b = bindObjectProps;
target._v = createTextVNode;
target._e = createEmptyVNode;
target._u = resolveScopedSlots;
target._g = bindObjectListeners;
target._d = bindDynamicKeys;
target._p = prependModifier;
}
这里我只是做了简单的插值模版,至于模版的其他用法,你可以自行尝试,主要的重点就是要理解render
函数的生成原理以及内容。
3、收集依赖(Collect as Dependency)。在模板中使用了哪个变量,就把那个变量观察起来(Watcher)
这部分主要实现了从vdom转化为真实DOM
、vnode新旧节点的对比
的操作。我在之前的文章《虚拟DOM(Virtual DOM)中动态更新视图的diff算法》中有过仔细的讲解,你可以点击链接进行查看。
二、数据更改触发的渲染流程分析
1、初次渲染过程
1、解析模版为render
函数(或在开发环境已完成,vue-loader
)。
2、触发响应式,监听 data
属性 getter setter
3、执行render
函数,生成vnode
,patch(elem.vnode)
。
2、更新过程
1、修改data,触发setter(此前在getter中已被监听)
2、重新执行render函数,生成newVnode
3、patch(vnode,newVnode)更新视图
至此,文章结束,感谢您的阅读!
网友评论