IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue源码阅读【番外篇】:为什么Proxy需要搭配Reflect来实现响应式? -> 正文阅读

[JavaScript知识库]Vue源码阅读【番外篇】:为什么Proxy需要搭配Reflect来实现响应式?

前言

我们都知道vue3.x版本是通过 Proxy 来实现的,用以解决2.X的一些缺陷。

但是我最近通过看 vue 源代码发现它内部很多地方是 Proxy、Reflect搭配一起使用的,例:

image.png image.png image.png 我们通过上面几张图可以看到 get、set、deleteProperty、has、ownKeys都用了 Reflect

基于此,这就是我写这篇文章的缘由,那我们探索一下为什么要搭配这两使用。

ProxyReflect 概念

  • Proxy: 代理,可以通过代理对象完成对目标对象的拦截,并在拦截后进行过滤和改写等操作,支持的拦截操作共 13
  • Reflect: 反射,它提供拦截 JavaScript 操作的方法。这些方法与 Proxy 的方法一一对应,也是 13 种。

Proxy简单使用示例:

const person = {
    name: '张三',
    get nickName() {
        return `${this.name}是坏蛋`
    }
}
const personProxy = new Proxy(person, {
    get(target, key, receiver) {
        console.log('进来了吧') 
        return target[key]
    }
})
console.log(personProxy.nickName)
// 先打印了:进来了吧
// 然后打印了:张三是坏蛋 

通过上面这个示例,我们发现他成功代理了,虽然我们没做什么处理。

不过 get 里面的 receiver 这个参数我们还没用到,receiver在这个时候表示代理对象(也就是personProxy)。

我们在 get 里面的return target[key],不能return receiver[key],否则会死循环。

我们再来个 Proxy 示例2:

const person = {
    name: '张三',
    get nickName() {
        console.log(this)
        return `${this.name}是坏蛋`
    }
}

const personProxy = new Proxy(person, {
    get(target, key, receiver) {
        return target[key]
    }
})

const person2 = {
    name: '李四'
}

Object.setPrototypeOf(person2, personProxy)

console.log(person2.nickName) 

上面这个示例种的console.log(this)console.log(person2.nickName) 会打印上面呢?

我们希望的应该是 person2这个对象李四是坏蛋 是吧,但实际上没有如期打印。

首先person2上面没有nickName这个属性,所以他会去personProxy上面找,然后返回了 person 上面的 nickName属性,nickName中的this指向了person他自己。

所以console.log(this)打印出来的是 person 对象,console.log(person2.nickName)打印出来的是person中的name,也就是张三是坏蛋

那我们怎么才能让他按照我们设想的那样打印李四是坏蛋

我们来到第三个示例:

const person = {
    name: '张三',
    get nickName() {
        console.log(this)
        return `${this.name}是坏蛋`
    }
}

const personProxy = new Proxy(person, {
    get(target, key, receiver) {
        return Reflect.get(target, key, receiver)
    }
})

const person2 = {
    name: '李四'
}

Object.setPrototypeOf(person2, personProxy)
console.log(person.nickName)        // 张三是坏蛋
console.log(personProxy.nickName)   // 张三是坏蛋
console.log(person2.nickName)       // 李四是坏蛋
/*
*   三次this打印的顺序如下:
*   { name: '张三', nickName: [Getter] }
*   { name: '张三', nickName: [Getter] }
*   { name: '李四' }
* */ 

我们通过在 get 里面 return Reflect.get(target, key, receiver) 来实现按我们想要的那样打印出来。

我们给 Reflectget 传递第三个参数(Proxy中的receiver),然后他就会修改调用时的this指向(也就是把指向person修改为:指向 person2)。

我们引用阮老师中的 Reflect 代码片段来说明一下 receiver,例:

var myObject = {
  foo: 1,
  bar: 2,
  get baz() {
    return this.foo + this.bar;
  },
};

var myReceiverObject = {
  foo: 4,
  bar: 4,
};

Reflect.get(myObject, 'baz', myReceiverObject) // 8 

如果name属性部署了读取函数(getter),则读取函数的this绑定receiver

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 22:45:33  更:2022-07-04 22:48:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/11 11:04:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码