从上面的 demo 可以看到在不用任何框架的情况下,我们要改变页面数据首先会先拿到 DOM,然后从 DOM 中拿到对应的数据,再去修改其他地方的数据,jQuery 的实现基本也是这种思路,页面数据的更新都是通过操作 DOM 去实现的,这意味着每次数据的更新都会操作至少一次 DOM,我们知道平凡的 DOM 操作可能会导致页面性能差而且代码不好维护等问题。而 Vue 的数据驱动视图实现可以很好的规避这些问题。
我们把上面的 demo 改一改
const input = document.querySelector('#input'); const text = document.querySelector('#text');
第二版 demo 我们把 data 作为数据中心,监听其中的数据变化去更新视图,但是只能监听到一个数据的变化,假如我们要监听多个数据的变化怎么办呢?再修改一下 demo
const input = document.querySelector('#input'); const text = document.querySelector('#text');
const data = { text: '', style: 'color:red', }; let val = ''; functionwalk(obj) { const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { defineReactive(obj, keys[i]); } } functiondefineReactive(obj, key, val) { if (arguments.length === 2) { val = obj[key]; } Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: functionreactiveGetter() { return val; }, set: functionreactiveSetter(newVal) { if (val === newVal) { return; } val = newVal; if (key === 'text') { changeText(val); } if (key === 'style') { console.log('change style'); } }, }); } walk(data); data.style = 'I change!'; functionchangeText(val) { text.innerText = val; } input.onchange = () => { data.text = event.target.value; };
这一版 demo 我们实现了监听 data 中所有数据的目标,但是不包括引用类型中包含的数据。这里有个问题,就是消费 text 数据的可能不止一个地方,可能有多个地方会消费 text,需要一一去进行视图的更新,怎么办呢?Vue 的做法是在 get 数据的时候做依赖收集,哪些地方用了 text 数据就把他放到一个数组里,在 set 中对所有依赖发布数据更新消息。