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中的双向数据绑定原理与常见操作技巧详解(3)
内容版权声明:除非注明,否则皆为本站原创文章。
转载注明出处:http://www.heiqu.com/362ef6629a1ca12f089c96089646daa5.html