1

从 Vue3 源码学习 Proxy & Reflect

 2 years ago
source link: https://segmentfault.com/a/1190000040990093
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

作者:CodeOz
译者:前端小智
来源:dev

有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

这两个功能都出现在ES6中,两者配合得非常好!

Proxy

proxy 是一个外来的对象,他没有属性! 它封装了一个对象的行为。它需要两个参数。

const toto = new Proxy(target, handler)

target: 是指将被代理/包裹的对象
handler: 是代理的配置,它将拦截对目标的操作(获取、设置等)

多亏了 proxy ,我们可以创建这样的 traps

const toto = { a: 55, b:66 }
const handler = {
 get(target, prop, receiver) {
   if (!!target[prop]) {
     return target[prop]
    }
    return `This ${prop} prop don't exist on this object !`
  }
}

const totoProxy = new Proxy (toto, handler)

totoProxy.a // 55
totoProxy.c // This c prop don't exist on this object !

每个内部对象的 "方法" 都有他自己的目标函数

下面是一个对象方法的列表,相当于进入了 Target:

object methodtargetobject[prop]getobject[prop] = 55setnew Object()constructObject.keysownKeys

目标函数的参数可以根据不同的函数而改变。

例如,对于get函数取(target, prop, receiver(proxy本身)),而对于 set 函数取(target, prop, value (to set), receiver)

我们可以创建私有属性。

const toto = {
   name: 'toto',
   age: 25,
   _secret: '***'
}

const handler = {
  get(target, prop) {
   if (prop.startsWith('_')) {
       throw new Error('Access denied')
    }
    return target[prop]
  },
  set(target, prop, value) {
   if (prop.startsWith('_')) {
       throw new Error('Access denied')
    }
    target[prop] = value
    // set方法返回布尔值
    // 以便让我们知道该值是否已被正确设置 !
    return true
  },
  ownKeys(target, prop) {
     return Object.keys(target).filter(key => !key.startsWith('_'))
  },
}

const totoProxy = new Proxy (toto, handler)
for (const key of Object.keys(proxy1)) {
  console.log(key) // 'name', 'age'
}

Reflect

Reflect 是一个静态类,简化了 proxy 的创建。

每个内部对象方法都有他自己的 Reflect 方法

object methodReflectobject[prop]Reflect.getobject[prop] = 55Reflect.setobject[prop]Reflect.getObject.keysReflect.ownKeys

❓ 为什么要使用它?因为它和Proxy一起工作非常好! 它接受与 proxy 的相同的参数!

const toto = { a: 55, b:66 }

const handler = {
  get(target, prop, receiver) {
   // 等价 target[prop]
   const value = Reflect.get(target, prop, receiver)
   if (!!value) {
      return value 
   }
   return `This ${prop} prop don't exist on this object !` 
  },
  set(target, prop, value, receiver) {
     // 等价  target[prop] = value
     // Reflect.set 返回 boolean
     return Reflect.set(target, prop, receiver)
  },
}

const totoProxy = new Proxy (toto, handler)

所以你可以看到 ProxyReflect api是很有用的,但我们不会每天都使用它,为了制作陷阱或隐藏某些对象的属性,使用它可能会很好。

如果你使用的是Vue框架,尝试修改组件的 props 对象,它将触发Vue的警告日志,这个功能是使用 Proxy :) !


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://dev.to/codeoz/proxy-r...

有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试完整考点、资料以及我的系列文章。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK