JS 实现对对象内参数的监听
哈嗨哈,这里是超会拖更的Kaiqisan,自从成为社畜之后就很少有空撰写博客了,今天下午后端那边服务器在维修,这就给了我很多整理博客的时间(摸鱼?)
使用过vue的人都知道vue拥有对参数监听的便捷方法,其原理就是使用数据劫持,在每次数据产生变化的时候触发其内在的函数,其书写方式如下
Object.defineProperty(obj, 'attr', {
get() {
return val
},
set(newValue) {
console.log('触发!');
val= newValue
}
})
监听的功能通过上述的Object.defineProperty 来实现,并借助了其第三个参数----属性描述符完成数据劫持,每次获取或修改数据,都将走过这一步,这也是vue的监听实现的底层逻辑。
如果开发者不设置这个高级选项,那么也就是进行一个默认的选项,getter默认返回当前对象的值,setter默认在修改值之后不进行任何操作。
下面的代码为具体的一个实例
let obj = {
name: 'John',
uid: '12345',
}
let _uid = obj.uid;
Object.defineProperty(obj, 'uid', {
get() {
return _uid
},
set(newValue) {
console.log('触发!');
_uid = newValue
}
})
setTimeout(() => {
obj.uid = '54321'
console.log(obj.uid);
}, 3000)
在打开页面之后的三秒后,输出框会自动修改对象的值并触发setter内的事件。 其中值得注意的是上面的一个临时参数_uid ,这个参数的作用就在用户获取uid的时候能够获取正确的数据。 因为一些内在原因,getter和setter无法调用自己所监听的对象属性。 所以需要借助第三方的参数_uid 来实现对象属性值的存储。
注意
这个监听的方法不仅可以实现对属性值的监听,也可以监听整个对象,如果对象内部的值产生变化就会回调setter。
let obj = {
name: 'John',
uid: '12345',
details: {
phoneNumber: '1234567890',
}
}
let details = obj.details;
Object.defineProperty(obj, 'details', {
get() {
return details
},
set(newValue) {
console.log('触发!');
details = newValue
}
})
setTimeout(() => {
obj.details.phoneNumber= '12345678901'
console.log(obj.details);
}, 3000)
扩展
上述的方法虽然能监听对象内部的属性值的变化,如果只是监听外部的对象,是很难具体获取内部的哪个属性值发生了变化。这个还需后序的比较,非常麻烦,所以,JS原生还有一种方法可以批量地监听,这不仅能够监听对象内部的多个属性,也可以极大地减少代码量。
这个方法就是使用Object.defineProperty 所衍生的Object.defineProperties
let obj = {
name: 'John',
uid: '12345',
phoneNumber: '123456789',
}
let name = obj.name
let uid = obj.uid
let phoneNumber = obj.phoneNumber
Object.defineProperties(obj, {
'name': {
get() {
return name
},
set(value) {
console.log('名字发生变化' + value)
name = value
}
},
'uid': {
get() {
return uid
},
set(value) {
console.log('uid发生变化' + value)
uid = value
}
},
'phoneNumber': {
get() {
return phoneNumber
},
set(value) {
console.log('phoneNumber发生变化' + value)
phoneNumber = value
}
}
})
setTimeout(() => {
obj.name = 'Tom'
}, 1000)
setTimeout(() => {
obj.uid = '123456'
}, 2000)
setTimeout(() => {
obj.phoneNumber = '123456789'
}, 3000)
总结
好了,我们了解了监听的底层逻辑了,是时候自己模拟一遍vue的watch的方法了!!
|