赞
踩
目录
1.基于 Object.defineProperty() 方法
数据代理是一种技术,通过代理、拦截对象属性及方法的访问请求,实现与该对象的交互。在Vue中,数据代理是指在Vue实例化一个组件时,Vue会将组件中的data属性中的数据转化为getter/setter,并将这些getter/setter注册到Vue的响应式系统中,在Vue实例中访问组件中的数据时,实际上是访问了这个getter/setter,它能统计出数据的依赖关系,并在数据变化时更新视图。
这么光看概念,乍一看确实会有点摸不着头脑。我会结合例子来讲讲数据代理是怎么实现的。
要清楚数据代理的底层实现,首先,我们必须得知道一个api,那就是Object.defineProperty()方法。
参考MDN官方文档,我们知道,Object.defineProperty() 是 JavaScript 中一个用于定义对象属性的方法。它接受三个参数:要定义属性的对象,属性名和描述符对象。
基本语法:
Object.defineProperty(obj, prop, descriptor)
其中:
描述符对象包含了四个可选属性:value、writable、enumerable 和 configurable:
这些属性具体的用法在这里我就不再赘述,如果有兴趣,可以去看看MDN的官方文档,里面对每个属性都有具体的示例去解释。我们直接来看看 Object.defineProperty()这个方法的作用。
- let obj1 = {
- foo: ''
- };
-
- let obj2 = {
- bar: 'Hello World!'
- };
-
- Object.defineProperty(obj1, 'bar', {
- get: function() {
- return obj2.bar;
- },
- set: function(value) {
- obj2.bar = value;
- }
- });
-
- console.log(obj1.bar); // 输出: 'Hello World!'
- obj1.bar = 'Goodbye!';
- console.log(obj2.bar); // 输出: 'Goodbye!'
- console.log(obj1.bar); // 输出:'Goodbye!'
在这个demo中,我们定义了两个对象obj1和obj2,它们分别有着各自的属性foo和bar。
然后,我们通过Object.defineProperty()在对象obj1中定义了一个原本obj1没有的属性‘bar’
然后设置了一个getter和一个setter。
这个getter的作用是:当用户获取obj1.bar这个属性值的时候,返回的是obj2.bar的值,也就是把对象obj2.bar的值赋给了obj1.bar。
这个setter的作用是:当用户修改obj1.bar时,就把修改后的值赋给obj2.bar。
通过setter和getter,我们就实现了数据代理。控制台打印结果如下所示:
那么这个结果是怎么来的呢?听听我的分析。
首先是第一个console.log(obj1.bar); 语句
因为用户要获取obj1.bar,所以就自动调用了getter,而get函数返回的值为obj2.bar的值,所以就打印了obj2.bar的值,为Hello World!。
然后是后面的语句:
obj1.bar = 'Goodbye!';
console.log(obj2.bar);
console.log(obj1.bar);
因为用户要修改obj1.bar的值为"Goodbye!",所以自动调用了setter,而set函数是把修改后的值赋给了obj2.bar,所以这时候打印obj2.bar,就会变成 Goodbye!
然后用户又要获取obj1.bar的值,这时候又要调用getter,把obj2.bar的值赋给obj1.bar,因为obj2.bar的值现在为 Goodbye!,所以打印出来的obj1.bar的值也为 Goodbye!
现在我们知道了 Object.defineProperty() 的用法,那我们就来看看Vue中数据代理的实现原理是什么。
在 Vue 实例化的过程中,Vue 会使用 Object.defineProperty() 给实例对象 data 中定义的每个属性都添加 getter 和 setter。这些 getter 和 setter 将实例属性访问代理到 data 对象中对应的属性上,这就实现了数据代理。
这句话是什么意思呢?我们还是通过示例来理解:
我们有这样的一个简单的模版
然后通过在控制台中查看vm实例的属性,我们可以看到一些端倪
我们并没有手动地去给days和months属性添加get和set函数,这都是Vue 使用了 Object.defineProperty() 给实例对象vm的 data 中定义的每个属性都添加 getter 和 setter。
这样,当用户修改data中的属性时,就会自动调用setter,改变视图中对应的属性值了。这就是数据代理的实现原理。
!!!注意:在实例化 Vue 对象时,Vue 会将传入的 data 对象的属性都添加到实例的 _data 对象中,并实现数据代理,使得这些属性能够被实例直接访问。如果没有_data对象,那么我们在模版中使用Vue实例中的data属性时,必须要在属性名前面加上_data.,所以Vue大大简化了我们的工作。
通过使用 Vue 框架的数据代理技术,我们可以实现简单、灵活、高效的数据绑定。借助于数据代理,可以实现以下优势:
实现自动依赖收集与响应
在 Vue 中,当 data 中的数据发生变化时,Vue 可以自动侦测到相应的依赖并且刷新页面,从而实现数据的响应式更新。
提高代码的可读性
通过代理,Vue 可以将数据与页面的操作进行相互绑定,从而实现数据的自动更新,避免了手动监听和更新数据的繁琐操作,使得代码更加简洁易读。
实现数据与视图的双向绑定
Vue 中的数据代理技术可以将数据与视图进行双向绑定,从而实现了数据的自动同步,使得数据的维护更加方便。
总的来说,Vue 数据代理是 Vue 框架中非常重要和核心的特性,可以提高代码编写的高效性和可读性。它通过对对象的访问进行代理与拦截,实现数据绑定与自动更新,使得开发流程更加高效并且方便维护。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。