Open sakila1012 opened 6 years ago
相信看过 vue 官方文档的同学,对这张图应该相当很熟悉了。
那么 vue 响应式是怎么实现的?
一般都会说数据劫持 + Object.defineProperty 下面是简单版的实现
Object.defineProperty
<div> <input type="text" id="txt"> <p id="show-txt"></p> </div> <script> var obj = {}; Object.defineProperty(obj, 'txt', { get: function(){ return obj; }, set: function(newValue) { document.getElementById('txt').value = newValue; document.getElementById('show-txt').innerHTML = newValue; } }) document.addEventListener('keyup', function(e) { obj.txt = e.target.value; }) </script>
标准版的如下:
const Observer = function(data) { for (var key in data) { defineReactive(data, key); } } const defineReactive = function(obj, key) { const dep = new Dep(); let val = obj[key]; Object.defineProperty(obj, key, { enumerable: true, configurable: true, get() { console.log('in get'); dep.depend(); return val; }, set(newVal) { if (newVal === val) { return; } val = newVal; dep.notify(); } }); } const observe = function (data) { return new Oserver(data) } const Vue = function (options) { const self = this; if (options && typeof options.data === 'function') { this._data = options.data.apply(this); } this.mount = function () { new Watcher(self, self.render); } this.render = function() { with(self) { _data.text; } } observer(this._data); } const Watcher = function(vm, fn) { const self = this; this.vm = vm; Dep.target = this; this.addDep = function(dep) { console.log('in watcher update'); fn(); } this.value = fn(); Dep.target = null; } const Dep = function() { const self = this; this.target = null; this.subs = []; this.depend = function() { if (Dep.target) { Dep.target.addDep(self); } } this.addSub = function(watcher) { self.subs.push(watcher); } this.notify = function() { for (var i=0; i<self.subs.length; i += 1) { self.subs[i].update(); } } } const vue = new Vue({ data() { return { text: 'hello world' } } }) vue.mount(); vue._data.text = '123';
相信看过 vue 官方文档的同学,对这张图应该相当很熟悉了。
那么 vue 响应式是怎么实现的?
一般都会说数据劫持 +
Object.defineProperty
下面是简单版的实现标准版的如下: