console
function nodeForEach(node, vm) {
let reg = /\{\{(.*)\}\}/
for (let i = 0; i < node.length; i++) {
const element = node[i];
if (element.nodeType === 1) {
const attr = element.attributes
for (let j = 0; j < attr.length; j++) {
const prop = attr[j];
if (prop.nodeName == 'v-model') {
const name = prop.nodeValue
element.value = vm[name]
element.addEventListener('input', function(e) {
vm[name] = e.target.value
})
}
}
}
if (element.nodeType === 3) {
if (reg.test(element.nodeValue)) {
const name = RegExp.$1.trim()
new Watcher(vm, element, name)
}
} else {
nodeForEach(element.childNodes, vm)
}
}
}
function defineReactive(obj, key, val) {
let dep = new Dep()
Object.defineProperty(obj, key, {
get: function() {
if (Dep.target) {
dep.addSub(Dep.target)
}
return val
},
set: function(newVal) {
if (val === newVal) {
return
}
val = newVal
dep.notify()
}
})
}
function Observe(obj, vm) {
for (const key of Object.keys(obj)) {
defineReactive(vm, key, obj[key])
}
}
function Dep() {
this.subs = []
}
Dep.prototype = {
addSub: function(sub) {
this.subs.push(sub)
},
notify: function() {
this.subs.forEach((sub) => {
sub.update()
})
}
}
function Watcher(vm, node, name) {
Dep.target = this
this.vm = vm
this.node = node
this.name = name
this.update()
Dep.target = null
}
Watcher.prototype = {
update: function() {
this.get()
this.node.nodeValue = this.value
},
get: function() {
this.value = this.vm[this.name]
}
}
function Vue(options) {
this.data = options.data
const id = options.el
Observe(options.data, this)
const dom = nodeForEach(document.getElementById(id).childNodes, this)
}
const vm = new Vue({
el: 'app',
data: {
hello: 'hello world!!!!'
}
})
<html>
<head></head>
<body>
<div id="app">
<input type="text" id="input" v-model="hello" />
<span>{{ hello }}</span>
</div>
</body>
</html>