Vue2
需求:双向数据绑定(数据变了,视图改变;视图改变,数据也变)
const data = {
name: 'ifer'
}
/* const tempData = { ...data }
Object.defineProperty(data, 'name', {
get() {
// 获取 name 的时候会走这儿
return tempData.name
},
set(newValue) {
// 设置 name 的时候会走这儿
tempData.name = newValue
}
})
// console.log(data.name) // 'ifer'
data.name = 'elser'
console.log(data.name) */
/* const tempData = { ...data }
Object.defineProperty(data, 'name', {
get() {
// 获取 name 的时候会走这儿
return tempData.name
},
set(newValue) {
// model => view => Data bindings
// #2 设置 name 的时候会走这儿
tempData.name = newValue
oP.innerHTML = newValue
oInput.value = newValue
}
})
// view => model => DOM Listeners
oInput.oninput = function (e) {
// #1
data.name = e.target.value
} */
/* oInput.oninput = function (e) {
oP.innerHTML = e.target.value
} */
Vue3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p id="oP"></p>
<input id="oInput" type="text" />
<script>
// 需求:双向数据绑定(数据变了,视图改变;视图改变,数据也变)
const data = {
name: 'ifer',
address: '北京'
}
/* const tempData = { ...data }
Object.keys(data).forEach(key => {
Object.defineProperty(data, key, {
get() {
return tempData[key]
},
set(newValue) {
tempData[key] = newValue
oP.innerHTML = newValue
oInput.value = newValue
}
})
})
oInput.oninput = function (e) {
data.address = e.target.value
} */
// 上面 Vue2 的问题:如果 data 里面有 100 个属性,那可不是要循环 100 次吗?
// p 就是一个代理,我对 p 的任何操作都会影响到 data
const p = new Proxy(data, {
get(target, attr) {
// 获取的时候触发
// console.log(target, attr)
// target => data
// attr => 属性
return target[attr]
},
set(target, attr, newValue) {
target[attr] = newValue
oP.innerHTML = newValue
oInput.value = newValue
}
})
// p.name = 'xxx'
// console.log(data.name);
/* p.name = 'xxx'
console.log(p.name) */
oInput.oninput = function (e) {
// p.address = e.target.value
p.test = e.target.value
}
</script>
</body>
</html>
结论
Vue2.0 使用 Object.defineProperty 对象以及对象属性的劫持+发布订阅模式,只要数据发生变化直接通知变化 并驱动视图更新。
Vue3.0 中的响应式采用了ES6中的
Proxy
方法。 可以理解成,在目标对象之前架设一层 “拦截” ,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
请登录后查看回复内容