//Vue
class Vue {
constructor(options) {
this.$el = options.el
this._data = options.data
this.$data = this._data
new Observer(this.$data)
}
}
//观察者
class Observer {
constructor(object) {
if (typeof object === "object") {
this.walk(object)
}
}
walk(object) {
Object.keys(object).forEach(key => {
this.defineReactive(object, key)
})
}
defineReactive(object, key) {
if (typeof object[key] === "object") {
this.walk(object[key])
}
let dep = new Dep()
let val = object[key]
Object.defineProperty(object, key, {
enumerable: true,
configurable: true,
get() {
Dep.target && dep.addSub(Dep.target)
return val
},
set(newValue) {
val = newValue
dep.notify(newValue)
}
})
}
}
//Dep
class Dep {
static target = null
constructor() {
this.subs = []
}
addSub(watcher) {
this.subs.push(watcher)
}
notify(newValue) {
this.subs.forEach(sub => {
sub.update(newValue)
})
}
}
let uid = 0
//watcher
class Watcher {
constructor(vm, key, cb) {
this.vm = vm
this.uid = uid++
this.cb = cb
Dep.target = this
this.value = findKey(this.vm.$data, key)
Dep.target = null
}
update(newValue) {
if (this.value !== newValue) {
this.value = newValue;
this.run();
}
}
run() {
this.cb(this.value)
}
}
let data = {
name: "花生",
age: 17,
job: {
salary: 22
}
}
let vm = new Vue({ data })
watch(data)
function findKey(object, target) {
if (typeof object !== "object") {
return;
}
if (Object.keys(object).includes(target)) {
return object[target]
} else {
Object.keys(object).forEach(key => {
if (typeof object === "object") {
findKey(object[key], target)
}
})
}
}
function watch(object) {
if (typeof object !== "object") {
return;
}
Object.keys(object).forEach(key => {
if (typeof object[key] === "object") {
watch(object[key])
} else {
new Watcher(vm, key, (value) => {
console.log("watcher", value);
})
}
})
}
重新整理vue2响应式
于 2022-08-16 11:07:24 首次发布