Vue是基于MVVM的一个前端框架,首先来介绍下什么是MVVM?
M:模型层,主要负责业务数据相关;
V:视图层,顾名思义,负责视图相关,细分下来就是html+css层;
VM:V与M沟通的桥梁,负责监听M或者V的修改,是实现MVVM双向绑定的要点;
其次,使用Object.defineProperty实现MVVM的表单数据双向绑定,当修改data属性之后,Vue立刻监听到,data属性被代理到vm上。
下面举一个例子
var obj = {}
var name = 'lili'
Object.defineProperty(obj, "name",{
get: function () {
console.log('get')
return name
},
set: function (newValue) {
console.log('set')
name = newValue
}
});
console.log(obj.name)
obj.name = 'xiaoming'
注:set是用来监听属性值被修改,get是获取某个属性时的监听,那有必要加get吗,有!当创建了很多属性时,可以通过get知道这个属性是否被用到,当没有被用过时,就不必要要监听这个属性。vue是数据驱动视图,数据的修改会触发视图变化,当没用到的数据被修改时,我们就不用管他,因为视图上就没用到,不必浪费时间来更新视图。
Vue使用了基于html的模版语法,模版的本质是字符串,但是它有逻辑,v-if,v-for等,最终还是要转化成html来显示,模版最终必须转化成js代码,因为转换为html渲染页面,必须js才能实现,因此,模版最终要转换成一个js函数(render函数),render函数执行之后,返回的是vnode,updateComponent中实现了vdom的patch,页面首次渲染执行updateComponent,data中每次修改属性,执行updateComponent
<div id="app">
<p>{{name}}</p>
</div>
上面的代码被转换的render函数
with(this) {
return _c(
'div',
{
attrs: {"id": "app"}
},
[
_c('p',[_v(_s(name))])
]
)
}
c是生成div结点,v是生成文本内容,_s其实是toString();
可以在Vue源码中搜索code.render,在
var code = generate(ast, options)
下面打印出code.render就可以看到模版被转换后的render函数
总结:Vue实现流程
- 解析模版成render函数
- 响应式开始监听
- 首次渲染,显示页面且绑定依赖
- data属性变化,触发rerender
Vue实现了数据和视图的分离,解耦,以数据驱动视图,只关系数据的变化,DOM操作被封装。