React-事件补遗-Proxy

By
写代码

上一篇留了一个代理Proxy没覆盖到,因为之前没怎么使用过,所以这篇补充一下相关内容。

Proxy用于定义基本操作自定义行为(比如:属性查找get,赋值set,枚举、函数调用等)。使用Proxy代理,可以在目标对象(target)进行操作之前,进行过滤和额外操作。

Proxy基本使用

target:代理虚拟化的对象,会用Proxy包装。可以是任何类型的对象,包括数组(native array)、函数(function),甚至另外一个Proxy。
handler:包含各种属性访问的方法,定义操作到达时进行何种操作。类似于操作系统中的traps概念。

注意,后面的操作,如果要通过handler的方法,所有操作必须都是在实例p上,而非原始的target对象上。

这里列举handler里方法中几个会用到的:

handler.apply(target, thisArg, argumentsList):以函数方式调用时的方法(trap);
handler.construct(target, argumentsList, newTarget):使用new操作符时的方法(trap);
handler.get(target, property, receiver):取值时的方法(trap);
handler.set(target, property, value, receiver):赋值时的方法(trap)。

ReactProxy处理事件

React中的合成事件(SyntheticEvent)就是使用代理实现的。每个具体事件,都带有不同的属性接口(interface),比如鼠标事件需要有点击位置(clientX、clientY)等,过渡事件有属性名(propertyName)等。每个都按同样的层次逆向扩展:具体事件 > 抽象层1 > … > 抽象层n > 基础合成事件。比如鼠标事件(SyntheticMouseEvent)的生成过程如下:

SyntheticMouseEventSyntheticUIEventSyntheticEvent的关系:

synthetic-mouse-event

鼠标合成事件

所以,合成事件的关键就在于SyntheticEvent对象的处理。直接跳到该文件,可以看到,合成事件主要使用的就是代理(Proxy),最终在apply方法(trap),返回另外一个Proxy,也是赋值时实际用到的:

这里construct使用了this.apply(...),即无论使用call/apply或者使用new操作符,都会转到apply统一处理,最终都返回对应的新Proxy对象。

调用过程

SyntheticEvent初始化时,会从this.constructor(这里是SyntheticMouseEvent)里取interface的字段来添加属性,这里的作用域this是由call函数的第一个参数(thisArgs)指定的作用域。

后面为SyntheticMouseEvent添加属性(_dispatchListener_dispatchInstances等),都会通过新Proxyset方法(trap)。

SyntheticEvent的作用总结

1、为各类事件制定统一的初始化、销毁行为;
2、使用代理,降低了代码耦合度(与具体事件无关),方便扩展和修改;
3、使用pool,提高复用率,避免资源浪费。

Proxy使用注意

相对来说,handler内容比较固定,常用的就是setgetconstructapply

target的类型

target决定了生成的代理对象的种类。比如,当target是对象时,不能使用newapply来进一步新建对象或调用函数方法。当target是数组时,可以用pushpop等方法。当target是函数是,可以使用new来生成目标对象,使用apply/call来调用函数。

1、对象(字面量或数组等)

比如可以在set里添加校验等内容,get里添加格式化输出等。

2、function或另一个Proxy

如果handler里定义了construct方法,使用new时,会进入该方法。
如果handler里定义了apply方法,使用apply/call时,会进入该方法。

0

Comments: 4

  1. 学习了,完全看不懂的技术知识

    05月08日
  2. 可惜不是网页代理。

    @none 05月20日
  3. 貌似非常久没来了,最近都不更新生活篇了啊。

    05月25日
    • @郑永 说的是哦,最近好像都没更新生活篇,安排上

      @venmax 06月01日

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

:razz: