共计 1183 个字符,预计需要花费 3 分钟才能阅读完成。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Observe demo</title>
</head>
<body>
<p> 响应式 demo</p>
<script src="./observe.js"></script>
</body>
</html>
function updateView(val) {console.log('视图更新', val)
}
// 从新定义数组原型
const arrayProto = Array.prototype
// 创立新对象,原型指向 arrayProto,再扩大新的办法不会影响原型
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift', 'unshift', 'sort', 'reverse', 'splice'].forEach(methodName => {arrayMethods[methodName] = function() {arrayProto[methodName].call(this, ...arguments)
updateView(this)
}
})
// 监听对象属性
function observer(target) {
// 不是对象或数组,间接返回
if (typeof target !== 'object' || target == null) return target
if (Array.isArray(target)) {target.__proto__ = arrayMethods} else {
// 从新定义各个属性(for in 也能够遍历数组)for(let key in target) {defineReactive(target, key, target[key])
}
}
}
// 监听属性的 get 和 set
function defineReactive(target, key, val) {
// 递归监听子属性(深度监听)observer(val)
Object.defineProperty(target, key, {get() {return val},
set(newVal) {if (newVal !== val) {updateView(newVal)
return newVal
}
}
})
}
const data = {
name: '张三',
age: 20,
obj: {address: '北京'},
a: {
b: {
c: {d: 'dddddddd'}
}
},
nums: [4,6,2,7,4,8,1]
}
// 监听 data
observer(data)
data.name = '李四'
data.age = 33
data.obj.address = '深圳'
data.a.b.c.d = 'd 扭转了'
data.nums.push(6)
data.nums.reverse()
data.nums.sort((a, b) => a - b)
正文完
发表至: javascript
2021-08-24