8Vue2.0响应式原理,使用的是Object.definedProperty进行数据响应式劫持,而Vue3.0使用的是Proxy进行数据据响应式劫持。
下面我做了Vue2.0的原理分析
前言
普通对象的定义,我们是没有办法监听到它的变化,所以普通对象是不具有响应式的,后来有了JS 的Object.definedProperty,这也是为什么Vue不支持IE8以下的版本,因为Object.definedProperty是IE8出来的对象语法,下面让我们一起去了解一下Object.definedProperty这个对象的方法,亲自感受一下Vue2.0的响应式原理的实现过程。
// 这种普通的对象,我们是没办法侦听到对象的改变的,
var obj1 = { a: 1, b: 2 };
obj1.a = 100
// 使用Object.defineProperty定义的对象,具有了get/set钩子,get和set就能侦听一个对象改变和取值,这就具有响应式了。
let obj = {};
let c = 3;
Object.definedProperty(obj2,'c',{
get() {
console.log('有人访问了 c');
return c;
}
set(newVal) {
console.log('有人修改了 c');
c = newVal;
}
})
// Vue
// 在这里定义响应式变量
var data = {
name: '1',
pass: '2'
}
// 第一步:把vue组件中data进行响应式劫持
// 劫持之后,做依赖收集(观察者模式、订阅发布模式),收集“响应式变量->DOM节点”的映射关系
var app = {};
Object.keys(data).forEach(key=> {
// 所谓的“劫持”,就是给普通对象的属性添加get/set钩子函数
// 当这个属性被访问时,触发get函数执行
// 当这个属性的值被修改时,触发set函数执行
Object.defineProperty(app, key, {
get() {
console.log(`你访问了${key}`)
return data[key]
},
set(newVal) {
console.log(`你修改了${key}`)
data[key] = newVal
Watcher()
}
})
})
// 第二步:初始化页面(通过Watcher进行页面初始化)
function init() {
document.getElementById('ipt').addEventListener('input', function(e){
// 当表单发生变化时,取出表单最新值,更新到响应式变量上
app.name = e.target.value
})
Watcher()
}
init();
// 第三步:当响应式变量发生变化时,触发set函数执行,再调用Watcher更新DOM
function Watcher() {
document.getElementById('ipt').value = app.name
document.getElementById('h3').innerText = app.name
}