我们已经实现了:修改输入框内容 => 在事件回调函数中修改属性值 => 触 发属性的set方法。
接下来我们要实现的是:发出通知dep.notify() => 触发订阅者update方法 => 更新视图。
这里的关键逻辑是:如何将watch添加到关联属性的dep中。
function observe(obj, vm) {
Object.keys(obj).forEach(function(key) {
defineReactive(vm, key, obj[key])
})
}function defineReactive(obj, key, val) {
var dep = new Dep()
Object.defineProperty(obj, key, {
get: function() {
if (Dep.target) {
// 添加订阅者watcher到主题对象Dep
dep.addsub(Dep.target)
}
return val
},
set: function(newVal) {
if (newVal === val) {
return
} else {
val = newVal
// 作为发布者发出通知
dep.notify()
}
}
})
}
function Dep () {
this.subs = []}
Dep.prototype = {
addsub: function(sub) {
this.subs.push(sub)
},
notify: function() {
this.subs.forEach(function(sub) {
sub.update()
})
}
}
function compile(node, vm) {
var reg = /{{(.*)}}/
if (node.nodeType === 1) {
var attr = node.attributes
for (var i = 0; i < attr.length; i++) {
if (attr[i].nodeName === 'v-model') {
var name = attr[i].nodeValue
node.addEventListener('input', function(e) {
vm[name] = e.target.value
})
node.value = vm[name] node.removeAttribute('v-model')
}
}
}
if (node.nodeType === 3) {
if (reg.test(node.nodeValue)) {
var name = RegExp.$1
name = name.trim()
// node.nodeValue = vm[name] new Watcher(vm, node, name)
}
}
}
function nodeToFragment(node, vm) {
var flag = document.createDocumentFragment()
var child
while (child = node.firstChild) {
compile(child, vm)
flag.appendChild(child)
}
return flag
}
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
this.methods = options.methods
var data = this.data
var el = options.el
observe(data, this)
var dom = nodeToFragment(document.querySelector(el), this)
document.querySelector(el).appendChild(dom)
}
var vm = new Vue({
el: '#app',
data: {
text: 123
}
})
希望本文所述对大家vue.js程序设计有所帮助。










