前言
vue2实现双向绑定的其中一环,即使用Object.defineProperty对data内部每个对象的所有property添加监控,当data中的对象被修改或者读取时,能监测到修改或读取的操作。
模拟VUE中Object.defineProperty拦截对象原理:
代码如下,在控制台修改obj.name的值,网页中的值也会随之修改
<!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> <div id="ddd"></div> <script> let obj=document.getElementById('ddd'); let tem=null; //监听对象obj的name属性,当访问name时执行get方法,修改name时执行set方法 Object.defineProperty(obj,'name',{ get(){ console.log('获取obj.name时执行此方法'); return tem }, set(value){ console.log('设置obj.name的值,value为修改的值'); tem=value; //当name数据修改后,网页显示内容会自动更新 obj.innerHTML=value; } }) obj.name='ld'; </script> </body> </html>
初始页面显示
修改obj.name后的页面显示
总结
vue底层会遍历data对象,给每个对象的属性都加上getter和setter方法,当访问或修改对象的某个属性时触发getter/setter方法,进而通知watcher发布订阅,修改关联的组件dom
注意
Object.defineProperty无法支持IE8以下版本的浏览器,所以vue2.0版本不支持IE8以下版本的浏览器
vue3的底层使用了 ES6 Proxy替代了Object.defineProperty,但是它对IE不友好(IE11都不支持),当vue3检测到当前浏览器为IE时会自动降级使用Object.defineProperty