Vue 实现流程:
1、把模板解析为 render 函数
· 运用 with
· 模板中的所有信息都被 render 函数包含
· 模板中用到的 data 中的属性,都变成了 JS 变量
· 模板中的 v-model v-for v-on 都变成了 JS 逻辑
· render 函数返回 vnode
Vue三要素之模板解析
Vue模板的本质是字符串,有逻辑如 v-if v-for 等(模板转换成 js 后【 render 函数 】通过js来实现逻辑,因为前端语言中,只有 JS 是图灵完备的语言),与 html 格式很像,但有很大区别。html 是静态的, Vue 的模板是动态的。不过,最终 Vue 的模板都要通过 js 转换为 html 来显示。
模板中的所有内容都包含在了 render 函数中。
模板:
<div id="app">
<div>
<input type="text" v-model="title">
<button v-on:click="add">submit</button>
</div>
<div>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
</div>
render 函数实例 (在 Vue 源码中通过 log(code.render)所得,vue.js 版本 5.2.13)
// _c 返回 Vnode
with(this){//this 就是 vm
return _c(
'div',
{
attrs:{"id":"app"}
},
[
_c(
'div',
[
_c(
'input',
{
directives:[
{
name:"model",
rawName:"v-model",
value:(title),
expression:"title"
}
],
attrs:{
"type":"text"
},
domProps:{
"value":(title)
},
on:{
"input":function($event){
if($event.target.composing) return;
title=$event.target.value
}
}
}
),
_v(" "),
_c(
'button',
{
on:{
"click":add
}
},
[_v("submit")]
)
]
),
_v(" "),
_c(
'div',
[
_c(
'ul',
_l(
(list),
function(item){
return _c(
'li',
[_v(_s(item))]
)
}
)
)
]
)
]
)
}
2、响应式开始监听
· Object.defineProperty
· 将data 的属性代理到 vm 上
// 模拟 Vue 响应式
var vm = {}
var data = {
name: 'zhangsan',
age: 20
}
var key, value
for(key in data){
(function (key){
Object.defineProperty(vm, key, {
get: function (){
console.log('get', data[key])
return data[key]
},
set: function (newVal){
console.log('set', newVal)
data[key] = newVal
}
})
})(key)
}
3、首次渲染,显示页面且绑定依赖
· 初次渲染,执行 updateComponent, 执行 vm._render()
· 执行 render 函数,会访问到本篇文章例子的 vm.list 和 vm.title,也就是 data 下的数据
· 会被响应式的 get 方法监听到
· 执行 updateComponent,会走到 vdom 的 patch 方法
· patch 将 vnode 渲染成 DOM,初次渲染完成
4、data 属性变化,触发 rerender (Dom repatch、模板 rerender)