{{message}}
class Vue {
constructor(options) {
this.$el = options.el
this.$data = options.data
this.$options = options
new Observer(this.$data)
Object.keys(this.$data).forEach(key => {
this._proxy(key)
})
new Compiler(this.$el, this)
new Computed(this, this.$options);
}
_proxy(key) {
console.log(key);
Object.defineProperty(this, key, {
configurable: true,
enumerable: true,
get() {
return this.$data[key]
},
set(newValue) {
this.$data[key] = newValue
}
})
}
}
class Observer {
constructor(data) {
this.data = data
Object.keys(data).forEach(key => {
this._defineReactive(this.data, key, data[key])
})
}
_defineReactive(data, key, value) {
const dep = new Dep()
Object.defineProperty(data, key, {
configurable: true,
enumerable: true,
get() {
if (Dep.target) {
dep.addSub(Dep.target)
}
return value
},
set(newValue) {
if (newValue === value) {
return
}
value = newValue
dep.notify()
}
})
}
}
class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
notify() {
this.subs.forEach(sub => {
sub.update()
})
}
}
const mustache = /\{\{(.+)\}\}/
class Compiler {
constructor(el, vm) {
this.el = document.querySelector(el)
this.vm = vm
this.frag = this._createFragment()
this.el.appendChild(this.frag)
}
_createFragment() {
const frag = document.createDocumentFragment()
let child;
while (child = this.el.firstChild) {
this._compile(child)
frag.appendChild(child)
}
return frag
}
_compile(node) {
// console.log(node);
if (node.nodeType === 1) {
const attrs = node.attributes
if (attrs.hasOwnProperty('v-model')) {
const nodeName = attrs['v-model'].nodeValue
node.addEventListener('input', e => {
this.vm[nodeName] = e.target.value
})
}
}
if (node.nodeType === 3) {
if (mustache.test(node.nodeValue)) {
const nodeName = RegExp.$1.trim()
console.log(nodeName);
new Watcher(node, nodeName, this.vm)
}
}
}
}
class Watcher {
constructor(node, key, vm) {
this.node = node
this.key = key
this.vm = vm
Dep.target = this;
this.update()
Dep.target = null
}
update() {
// console.log(this.vm.$data[this.key]);
this.node.nodeValue = this.vm[this.key]
}
}
class Computed {
constructor(vm, options) {
this.vm = vm
this.computed = this.options.computed
Object.keys(computed).forEach(function (key) {
Object.defineProperty(vm, key, {
get: typeof computed[key] === "function" ? computed[key] : computed[key].get,
set() { }
})
})
};
}
const app = new Vue({
el: '#app',
data: {
message: '哈哈哈'
}
})
一键复制
编辑
Web IDE
原始数据
按行查看
历史