(一)什么是VUE响应式
组件的data一旦变化,立即触发视图更新,是实现数据驱动视图的第一步
(二)响应式核心
API:Object.defineProperty()
(三)监听范围 -- 主要考虑的情况
肯定是要监听对象的,因为组件的 data 就是一个对象,那会有以下几种情况
(1)data 对象里面只有一层 如:
{ name: 'zfb',
age: 23
}
(2)data 里面对象嵌套多层,需要深度监听,监听每一个对象的属性
{
name: 'zfb',
school: {
name: 'Northeast Agricultural University',
address: 'Harbin',
major: {
mainMajor: 'Veterinary Medicine',
otherMajor: 'computer'
}
}
}
(3)监听数组
data 中某一个属性值是一个数组的情况也很常见。push、pop、shift、unshift 等数组操作改变数组后,触发页面刷新
(四)代码
<!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>
<script>
const arrAllMethods = Array.prototype
const arrProto = Object.create(arrAllMethods) // Object.create 不能在数组的原型航进行更改 保留原生的
const updateMethods = ['push', 'shift', 'unshift', 'pop', 'splice', 'sort', 'reverse']
updateMethods.forEach(method => {
arrProto[method] = function () {
arrAllMethods[method].call(this, ...arguments)
updatePage()
}
});
// arrAllMethods
// 更新页面函数
function updatePage () {
console.log('页面更新', data)
}
// 监听
function observe (object) {
if (typeof object !== 'object' || object === null) {
return
}
// 如果是数组就不走 watchChange
if (Array.isArray(object)) {
object.__proto__ = arrProto // 将数组的原型重新赋值
return
}
for (var key in object) { // 循环对象
watchChange(object, key, object[key])
}
}
// 具体监听每一个属性
function watchChange (obj, key, value) {
// 如果是数组或者对象 需要深度监听 要监听到对象的每一个属性
if (typeof value === 'object') {
observe(value)
return
}
Object.defineProperty(obj, key, {
get: function () {
return value
},
set: function (newValue) {
if (value !== newValue) {
observe(newValue) // 设置新值也需要深度监听 可能字符串修改成对象
value = newValue
updatePage()
}
}
})
}
let data = {
name: 'zfb',
school: {
name: 'Northeast Agricultural University',
address: 'Harbin',
major: {
mainMajor: 'Veterinary Medicine',
otherMajor: 'computer'
}
},
score: [100, 98, 68]
}
// 监听data值变化函数
observe(data)
data.name = 'dd'
delete data.name // 无法监听 删除属性 this.$delete
data.age = '23' // 新增属性 无法监听 this.$set
data.school.name = { text: 'dd' } // 深度监听
data.school.name.text = 22 // 可以监听
data.school.major = {} // 无法监听 得修改到具体的根属性
data.score.push(1)
</script>
</body>
</html>
(五)缺点
(七)总结
数组:更改在原生数组原型的基础上更改Vue数组的原型 目的的为了监听数组改变 更新视图
对象:利用Object.defineProperty() 监听对象的属性变化,注意 深层对象监听(深度监听)需要循环绑定监听