MVVM - Model View ViewModel
总所周知,Vue是目前比较流行的MVVM前端框架,其核心在于VM。Vue通过MVVM架构将数据和视图进行了分离,将两者进行解耦,通过VM层构建两者的沟通渠道。其中View层通过事件绑定触发Model中data的更新,而Model中的数据可以通过数据绑定来及时针对数据的变化更新相应的视图。
Vue MVVM框架的三大要素
1. 响应式
问题: Vue如何监听到data的每个属性变化?
- 什么是响应式?
Vue能监听到数据的修改,并根据数据的修改更新对应的视图,而视图中数据的修改也能触发数据的更新。 - Vue是通过何种方式实现响应式的?
通过Object.defineProperty,使用get()和set()方法,使用get/set获取数据的值和对
data属性值进行修改,由于是函数,则可以加入自定义的代码,如监听到变化是否需要更新对应的视图,通过updateComponent函数实现。 - 为什么可以直接通过this获取数据,而不用通过this.data?
因为data属性被代理到vm上,在Object.defineProperty
代码实现:
通过闭包和立即执行函数保存每一个key值及对应的get/set函数,块级作用域
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)
}
2. 模板引擎
问题: Vue的模板如何被解析,指令如何处理?
- 模板是什么
本质是字符串,有逻辑, 模板中所有信息需要被解析成vnode。
通过render函数对模板进行解析,render函数会解析模板的所有信息,包含属性,数据,事件等。 - 模板中如何实现逻辑及实现v-model等指令
在render函数中执行对应的逻辑,如循环,条件等,返回不同的vnode,v-model则通过上述介绍的,在get, set中进行监听即可。
3. 渲染
问题: Vue的模板如何被渲染成html,以及渲染过程?
- updateComponent中实现vdom的patch
- 页面首次渲染执行updateComponent
- data中每次修改属性,执行updateComponent
vue的整个实现流程
- 解析模板成render函数
Vue中使用了with,模板中所有信息都被render函数包含,模板中用到的data中的属性,都变成了JS变量,模板中的v-model, v-for, v-on都变成JS逻辑。render函数的最终结果返回vnode - 响应式开始监听
Object.defineProperty监听set和get,将data的属性代理到vm上 - 首次渲染,显示页面,且绑定依赖
初次渲染,会执行updateComponent和vm._render(),具体流程如下:
执行render函数过程中,会访问到vm.list和vm.title 即会被响应式的get方法监听到
执行updateComponent,会走到vdom的patch方法
patch将vnode渲染成DOM,初次渲染完成 - data属性变化,触发rerender
修改属性,被响应式的set监听到,set中执行updateComponent, updateComponent重新执行vm._render(),生成的vnode和preVnode,通过patch进行对比,渲染到html中
问题: 为什么要监听get,不直接监听set?
data中有很多属性,会被用到的走get,不会用到的不走。避免不必要的重复渲染
网友评论