Vue源码分析-MVVM实现原理
什么是MVVM
MVVM
是Model-View-ViewModel的简写。即模型-视图-视图模型。
- 模型指的是后端传递的数据。
- 视图指的是所看到的页面。
- 视图模型是mvvm模式的核心,它是连接view和model的桥梁。它能够将数据转化为视图,也能将视图转化为模型,其中视图与模型是不能直接进行通信。
- ViewModel通过DOM事件监听视图数据的变化,一旦数据发生改变则更新model数据; Model通过数据绑定机制,将数据渲染到视图的Dom上,从而实现了数据的双向绑定。
参考:
http://baijiahao.baidu.com/s?id=1596277899370862119&wfr=spider&for=pc
https://segmentfault.com/a/1190000018399478
https://www.cnblogs.com/gaosong-shuhong/p/9253973.html
Vue中的MVVM实现原理
一、数据劫持-
1、Object.defineProperty(obj, key, atts)
在创建Vue实例的时候,通过data属性来管理数据:
new Vue({
el: "#app",
data:{
}
});
然后使用Object.defineProperty(obj, key, atts)
方法来对data进行get和set操作。例如:
Object.keys(data).forEach(key => {
// 开始劫持
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() { // 当取值时,触发get方法
return value;
},
set(newValue) { // 给对象赋值的时候,触发set方法
console.log(newValue)
}
})
});
以上方法就是对data对象的所有属性进行劫持,当取值的时候,触发get方法,当赋值的时候触发set方法,这样就可以在get和set方法中添加一些逻辑处理。
2、vue源码中的数据劫持
vue源码中的数据劫持在目录/src/core/observer/index.js
中的Observer
class类里,在调用walk
函数时,调用defineReactive
函数,代码如下:
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
// #7981: for accessor properties without setter
if (getter && !setter) return
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = !shallow && observe(newVal)
dep.notify()
}
二、绑定el和编译模板以及指令
在使用vue的时候,创建vue实例会绑定el元素节点:
new Vue({
el: "#app",
....
});
在绑定el这个过程的时候,会把id为app
的dom节点下的所有dom编译进内存中,然后在内存中解析出相应的指令,替换模板数据,并添加更新数据函数和初始化相应的订阅者。
- 编译指令和模板的时候,会把data中的数据赋值给DOM
- 初始化数据后,再为每一个指令或者模板对象初始化观察者,初始化观察者的时候,获取旧值,在获取旧值的时候触发数据劫持的get方法,在get方法中将观察者添加到订阅者的数组中(即是发布观察者),在数据劫持的set方法中,触发订阅,会去执行观察者的更新方法,再执行观察者回调方法,将新值传给编译指令器中,从而达到了数据更新。
三、MVVM原理图
MVVM的简单实现
GitHub源码:https://github.com/RenZhongrui/vue-learn/tree/master/001-vue-mvvm
推荐阅读
-
Linux使用libnet实现ARP攻击脚本原理分析以防被攻击
-
并发编程CountDownLatch,CyclicBarrier,Semaphore实现原理分析
-
thinkPHP框架RBAC实现原理分析
-
使用.Net Core + Vue + IdentityServer4 + Ocelot 实现一个简单的DEMO +源码
-
vue如何实现observer和watcher源码解析
-
PHP设计模式入门之状态模式原理与实现方法分析
-
百度工程师讲PHP函数的实现原理及性能分析(一)
-
MyBatis接口的简单实现原理分析
-
百度工程师讲PHP函数的实现原理及性能分析(二)
-
Spring Cloud动态配置实现原理与源码分析