class Observer {
constructor(value) {
this.value = value
def(value, '__ob__',this)
if (Array.isArray(value)) {
}else {
this.walk(value)
}
}
walk (obj) {
const keys = Object.keys(obj)
keys.forEach(key => {
defineReactive(obj, key)
})
}
}
class Dep {
constructor () {
this.subs = []
}
addSub (sub) {
this.subs.push(sub)
}
removeSub (sub) {
this.subs = this.subs.filter(item !== sub)
}
depend () {
if (window.target) {
this.addSub(window.target)
}
}
notify () {
const subs = this.subs.slice()
subs.forEach(sub => sub.update())
}
}
class Watcher {
constructor (vm,expOrFn,cb) {
this.vm = vm;
this.cb = cb;
this.getter = parsePath(expOrFn)
this.value = this.get()
}
get () {
window.target = this;
const vm = this.vm
let value = this.getter.call(vm, vm)
window.target = undefined;
return value
}
update () {
const oldValue = this.value
this.value = this.get()
console.log('update')
this.cb.call(this.vm, this.value, oldValue)
}
}
function def(obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
})
}
function defineReactive(obj, key, val, customSetter, shallow) {
if (arguments.length === 2) {
val = obj[key]
}
if (typeof val === 'object') {
new Observer(val)
}
const dep = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get(){
console.log(`${key}属性被读取了`);
dep.depend()
return val;
},
set(newVal){
if(val === newVal){
return
}
console.log(`${key}属性被修改了`);
val = newVal;
dep.notify()
}
})
}
const bailRE = /[^\w.$]/
function parsePath (path) {
if (bailRE.test(path)) {
return
}
const segments = path.split('.')
return function (obj) {
for (let i = 0; i < segments.length; i++) {
if (!obj) return
obj = obj[segments[i]]
}
return obj
}
}
let car = new Observer({
'brand':'BMW',
'price':3000
}).value
let watch = new Watcher ({
car: car,
} ,'',[]).vm.car
watch.brand = 1
console