vue源码分析-基础的数据代理检测

本文深入分析了Vue.js中的数据代理,包括Object.defineProperty和Proxy在数据代理中的应用,以及initProxy在模板渲染时的数据筛选过滤。重点讨论了如何通过这两种方式实现数据的拦截和响应式系统的构建,同时也揭示了数据代理在不同场景下的优势和局限性。
摘要由CSDN通过智能技术生成

简单回顾一下这个系列的前两节,前两节花了大量的篇幅介绍了Vue的选项合并,选项合并是Vue实例初始化的开始,Vue为开发者提供了丰富的选项配置,而每个选项都严格规定了合并的策略。然而这只是初始化中的第一步,这一节我们将对另一个重点的概念深入的分析,他就是数据代理,我们知道Vue大量利用了代理的思想,而除了响应式系统外,还有哪些场景也需要进行数据代理呢?这是我们这节分析的重点。

2.1 数据代理的含义

数据代理的另一个说法是数据劫持,当我们在访问或者修改对象的某个属性时,数据劫持可以拦截这个行为并进行额外的操作或者修改返回的结果。而我们知道Vue响应式系统的核心就是数据代理,代理使得数据在访问时进行依赖收集,在修改更新时对依赖进行更新,这是响应式系统的核心思路。而这一切离不开Vue对数据做了拦截代理。然而响应式并不是本节讨论的重点,这一节我们将看看数据代理在其他场景下的应用。在分析之前,我们需要掌握两种实现数据代理的方法: Object.definePropertyProxy

2.1.1 Object.defineProperty

官方定义:Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

基本用法:

Object.defineProperty(obj, prop, descriptor)

Object.defineProperty()可以用来精确添加或修改对象的属性,只需要在descriptor对象中将属性特性描述清楚,descriptor的属性描述符有两种形式,一种是数据描述符,另一种是存取描述符,我们分别看看各自的特点。

  1. 数据描述符,它拥有四个属性配置
  • configurable:数据是否可删除,可配置
  • enumerable:属性是否可枚举
  • value:属性值,默认为undefined
  • writable:属性是否可读写
  1. 存取描述符,它同样拥有四个属性选项
  • configurable:数据是否可删除,可配置
  • enumerable:属性是否可枚举
  • get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined
  • set:一个给属性提供 setter 的方法,如果没有 setter 则为 undefined

需要注意的是: 数据描述符的value,writable 和 存取描述符中的get, set属性不能同时存在,否则会抛出异常。 有了Object.defineProperty方法,我们可以方便的利用存取描述符中的getter/setter来进行数据的监听,这也是响应式构建的雏形。getter方法可以让我们在访问数据时做额外的操作处理,setter方法使得我们可以在数据更新时修改返回的结果。看看下面的例子,由于设置了数据代理,当我们访问对象oa属性时,会触发getter执行钩子函数,当修改a属性的值时,会触发setter钩子函数去修改返回的结果。

var o = {
   }
var value;
Object.defineProperty(o, 'a', {
   
    get() {
   
        console.log('获取值')
        return value
    },
    set(v) {
   
        console.log('设置值')
        value = qqq
    }
})
o.a = 'sss' 
// 设置值
console.log(o.a)
// 获取值
// 'qqq'


前面说到Object.definePropertygetset方法是对对象进行监测并响应变化,那么数组类型是否也可以监测呢,参照监听属性的思路,我们用数组的下标作为属性,数组的元素作为拦截对象,看看Object.defineProperty是否可以对数组的数据进行监控拦截。

var arr = [1,2,3];
arr.forEach((item, index) => {
   
    Object.defineProperty(arr, index, {
   
        get() {
   
            console.log('数组被getter拦截')
            return item
        },
        set(value) {
   
            console.log('数组被setter拦截')
            return item = value
        }
    })
})

arr[1] = 4;
console.log(arr)
// 结果
数组被setter拦截
数组被getter拦截
4

显然,**已知长度的数组是可以通过索引属性来设置属性的访问器属性的。**但是数组的添加确无法进行拦截,这个也很好理解,不管是通过arr.push()还是arr[10] = 10添加的数据,数组所添加的索引值并没有预先加入数据拦截中,所以自然无法进行拦截处理。这个也是使用Object.defineProperty进行数据代理的弊端。为了解决这个问题,Vue在响应式系统中对数组的方法进行了重写,间接的解决了这个问题,详细细节可以参考后续的响应式系统分析。

另外如果需要拦截的对象属性嵌套多层,如果没有递归去调用Object.defineProperty进行拦截,深层次的数据也依然无法监测。参考Vue3源码视频讲解:进入学习

2.1.2 Proxy

为了解决像数组这类无法进行数据拦截ÿ

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用vue-video-player是将video.js集成到了Vue中,因此在考虑到Vue项目的技术融合性方面比较好。而video.js本身的包比较大,使用起来不够灵活,修改UI时需要通过插件实现。另外,还有其他的播放器选择,如clappr和flv.js,但vue-video-player在技术融合和功能方面更具优势。在组件中使用vue-video-player,需要引入相应的CSS文件和引入videoPlayer组件,并在components中注册该组件。这样就可以在组件中使用vue-video-player来实现视频播放的功能。 关于数据流的问题,需要根据具体的场景来确定。在vue-video-player中,可以通过props属性将父组件中的数据传递给子组件,实现数据的流动。同时,子组件也可以通过事件来将数据传递给父组件,实现双向的数据流动。具体的数据流方案需要根据具体的需求来确定,可以根据Vue的官方文档和vue-video-player的文档来了解更多的使用方法和示例。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [vue使用vue-video-player实现视频播放:](https://blog.csdn.net/weixin_53791978/article/details/127757827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [vue2.0使用vue-video-player实现直播](https://blog.csdn.net/weixin_44700978/article/details/118887327)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值