核心API - Object.defineProperty
Proxy(Vue3.0 处理响应式), 兼容性不好, 且无法polyfill
Object.defineProperty基本用法
let data = {}
let name = 'jack'
Object.defineProperty(data, 'name', {
get: function () {
console.log('get')
return name
},
set: function (newName) {
console.log('set', name, newName)
name = newName
}
})
console.log(data.name)
data.name = 'Mary'
console.log(data.name)
Object.defineProperty实现监听式
- 监听对象, 借助 for..in 对各属性重新defineProperty并监听。
- 深度监听, defineReactive中调用observe(val), 实现递归(监听)
- 监听数组,拦截数组,重写原型,添加监听。借助Object.create, 重写目的在于防止全局数组方法被污染。
```
if (Array.isArray(target)) {
} function defineArrayProperty () { const oldArrayProperty = Array.prototype; const arrayProto = Object.create(Array.prototype) const methods = [‘push’, ‘pop’, ‘shift’, ‘unshift’, ‘splice’]; methods.forEach((methodName) => {target.__proto__ = defineArrayProperty()
}) return arrayProto }arrayProto[methodName] = function() {
updateView()
oldArrayProperty[methodName].call(this, ...arguments)
}
附录(实现):
function defineReactive(target, key, value) {// 重新定义属性,监听起来 observer(value) // 深度监听 Object.defineProperty(target, key, { // 核心 API get() { return value }, set(newValue) { if (newValue !== value) { observer(newValue) // 深度监听 value = newValue // 设置新值,注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值 updateView() } } }) }
function observer(target) { // 监听对象属性 if (typeof target !== ‘object’ || target === null) { return target // 不是对象或数组 } if (Array.isArray(target)) { // 防止污染全局的 Array 原型 target.proto = defineArrayProperty() } for (let key in target) { // 重新定义各个属性(for in 也可以遍历数组) defineReactive(target, key, target[key]) } } ``` 考点: 组件data的数据一旦变化, 立刻触发视图更新。实现数据驱动视图的第一步是什么?