JSFiddle - React, Tailwind, and code Playground
HTML
<div>
<p class="text"></p>
<div>
JavaScript
class Dep {
constructor () {
// 收集当时属性的观察者
this.subs = []
}
}
Dep.target = null
function observer (vm, key, val) {
let dep = new Dep()
Object.defineProperty(vm, key, {
/**
* get主要做两个事情
* 1. 收集观察当前key的wathcer(即依赖当前key的操作)
* 2. 获取值
*/
get () {
// 这是作用1
if (Dep.target) {
dep.subs.push(Dep.target)
}
// 这是作用2
return val
},
/**
* set也是两个事情
* 1. 修改目标值
* 2. 执行依赖当前key的watcher
*/
set (newVal) {
val = newVal
for(cb of dep.subs) {
cb.call(vm)
}
}
})
}
class Watcher {
/**
* vm: 实例
* cb: 依赖某属性的操作函数
*/
constructor (vm, cb) {
// 把当前的操作挂载到Dep上
Dep.target = cb
/**
* 执行操作
* 1. 进行操作的初始化
* 2. 触发属性的get方法
*/
cb.call(vm)
Dep.target = null
}
}
class Vue {
constructor (options) {
let data = options.data
let renderFun = options.renderFun
// initData
Object.keys(data).forEach(key => {
observer(this, key, data[key])
})
// 模拟计算属性,watcher,指令等依赖属性的操作
Object.keys(renderFun).forEach(key => {
new Watcher(this, renderFun[key])
})
}
}
let vm = new Vue({
// 假设有data
data: {msg: 1},
// 有某个v-text操作,我们抽象为vText函数,依赖属性msg
renderFun: {
vText () {
document.querySelector('.text').innerText = this.msg + 'text'
}
}
})
setInterval(() => {vm.msg++}, 1000)