vue2.x 数据响应式核心原理
官网描述:当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
实现对一个属性进行监听转换
<script>
// 模拟vue中的data
let data = {
msg:'xuke'
}
// 模拟vue的 实例
let vm = {}
// 数据劫持:当我们访问或者设置 vm 中的成员的时候,做一些干预的操作
Object.defineProperty(vm,'msg',{ // 第一参数为对象,第二个参数为对象中的属性,第三个参数为属性描述符,我们可以为msg设置get和set方法
// 可枚举可遍历
enumerable:true,
// 可配置,可以使用delete删除,可通过 defineprototype重新定义
configurable:true,
// 当获取值时执行的方法
get(){
console.log("获取我了")
return data.msg
},
// 当设置值时执行的方法
set(newVable){
console.log("设置我了")
if(data.msg === newVable){
return
}
data.msg = newVable
// 更新dom
document.querySelector("#app").textContent = data.msg
}
})
// 测试
vm.msg = 'xuke haha'
console.log(vm.msg)
</script>
实现对多个属性的监听
思路:我们将数据劫持监听封装成一个函数,函数中我们遍历data中得每个属性,并使用循环的方式给每个属性加监听劫持
<script>
// 模拟vue中的data
let data = {
msg: 'xuke',
count: 10
}
// 模拟vue的 实例
let vm = {}
proxyData(data)
// 将监听的属性封装成一个函数
function proxyData(data) {
Object.keys(data).forEach(key => {
// 数据劫持:当我们访问或者设置 vm 中的成员的时候,做一些干预的操作
Object.defineProperty(vm, key, { // 第一参数为对象,第二个参数为对象中的属性,第三个参数为属性描述符,我们可以为msg设置get和set方法
// 可枚举可遍历
enumerable: true,
// 可配置,可以使用delete删除,可通过 defineprototype重新定义
configurable: true,
// 当获取值时执行的方法
get() {
console.log("获取我了")
return data[key]
},
// 当设置值时执行的方法
set(newVable) {
console.log("设置我了")
if (data[key] === newVable) {
return
}
data[key] = newVable
// 更新dom
document.querySelector("#app").textContent = data[key]
}
})
})
}
// 测试
vm.msg = 'xuke haha'
console.log(vm.msg)
</script>
Vue3.x 数据响应原理
区别2.x:
- 直接监听对象 而非属性
- ES6中新增,IE不支持,性能由浏览器优化
- 通过ES6新增Proxy进行数据监听
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
xuke
</div>
<script>
// 模拟vue中的data
let data = {
msg: 'xuke',
count: 10
}
// 模拟vue的 实例
let vm = new Proxy(data,{
// 执行代理行为的函数
// 当访问vm的成员会执行
get(target,key){
console.log("执行get了")
return target[key]
},
// 当设置vm的成员会执行
set(target,key,newValue){
console.log("设置set了")
if(target[key]===newValue){
return
}
target[key]=newValue
document.querySelector("#app").textContent = target[key]
}
})
// 测试
vm.msg = 'xuke haha'
console.log(vm.msg)
</script>
</body>
</html>