MVVM
MVVM 的关注点是操作 javascript,而不用关心如何操作 DOM。
Model
数据层,没有其他成分
const data = {
a: 1,
b: 2
}
View
视图层,展示数据
<div>
<span id="text" data-text="123"></span>
</div>
ViewModel
用来连接 Model 和 View,使得 Model 和 View 完全解耦。
Object.defineProperty()
对象的属性有两种类型,数据属性和访问器属性。这里要用的是访问器属性里面的 get 和 set 两个内部特征。通过 Object.defineProperty() 可以控制访问器的特征
当然 Object.defineProperties() 也是可以的
const person = {
name: 'Jerry'
}
reactiveName = 'Jerry'
Object.defineProperty(person, 'name', {
configurable: true,
enumerable: true,
get() {
return reactiveName + '~'
},
set(value) {
reactiveName = value + '123'
}
})
// 改变属性,触发 set
person.name = 'Tom'
console.log(person.name) // Tom123~
Vue.js 中的双向绑定
Vue.js 的双向绑定便是利用 Object.defineProperty() 、 MVVM 模式和发布订阅模式来实现的。
VM的初始化
将 View 和 Model 的数据传入ViewModel。Model的数据比较简单就是一个对象。View 中的数据会抽取指令、方法和直接引用的变量。
利用 Object.defineProperty() 设置这些变量的 get set 方法。
发布订阅模式
订阅者便是这些变量,发布者是变量的 set 。
具体实现
Data: 每个组件实例都对应一个 Data,可以理解成 Model。在组件渲染过程中使用过的变量都会触发 Object.defineProperty() 的 get
Watcher: 每个组件实例对应一个 Watcher。它会订阅这个组件渲染过程中的变量变化。当变量被修改触发 set,这时变量作为一个发布者通知 Watcher 这个订阅者
Component Render Function: 处理 Watcher 触发之后的数据逻辑