function defineReactive(obj, key, val) {
const dep = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
if (Dep.target) {
dep.depend()
}
return val
},
set(newVal) {
if (newVal === val) return
val = newVal
dep.notify()
}
})
}
class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
depend() {
if (Dep.target) {
Dep.target.addDep(this)
}
}
notify() {
this.subs.forEach(sub => sub.update())
}
}
class Watcher {
constructor(vm, expOrFn, cb) {
this.vm = vm
this.cb = cb
this.getter = expOrFn
this.value = this.get()
}
get() {
Dep.target = this
const value = this.getter.call(this.vm, this.vm)
Dep.target = null
return value
}
update() {
const oldValue = this.value
this.value = this.get()
this.cb.call(this.vm, this.value, oldValue)
}
}
class VNode {
constructor(tag, data, children, text, elm) {
this.tag = tag
this.data = data
this.children = children
this.text = text
this.elm = elm
this.key = data && data.key
}
}
function patch(oldVnode, vnode) {
if (sameVnode(oldVnode, vnode)) {
patchVnode(oldVnode, vnode)
} else {
const elm = oldVnode.elm
const parent = elm.parentNode
createElm(vnode)
parent.insertBefore(vnode.elm, elm)
parent.removeChild(elm)
}
}
function patchVnode(oldVnode, vnode) {
const elm = vnode.elm = oldVnode.elm
const oldCh = oldVnode.children
const ch = vnode.children
if (oldVnode === vnode) return
if (vnode.text) {
elm.textContent = vnode.text
} else {
if (oldCh && ch) {
updateChildren(elm, oldCh, ch)
}
}
}