关于vuetrigger的信息

本篇文章给大家谈谈vuetrigger,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

Vue3.0 响应式原理

Vue3 使用 Proxy 对象重写响应式系统,这个系统主要有以下几个函数来组合完成的:

1、reactive:

接收一个参数,判断这参数是否是对象。不是对象则直接返回这个参数,不做响应式处理

创建拦截握梁器对象 handler, 设置 get/set/deleteProperty

get

收集依赖(track)

返回当前 key 的值。

如果当前 key 的值是对象,则为当前 key 的对象创建拦截器 handler, 设置 get/set/deleteProperty

如果当前的 key 的值不是对象租枯,则返回当前 key 的值

set

设置的新值和老值不相等时,更新为新值,并触发更新(trigger)

deleteProperty

当前对象有这个 key 的时候,删除这个 key 并触发更新(trigger)

返回段型运 Proxy 对象

2、effect: 接收一个函数作为参数。作用是:访问响应式对象属性时去收集依赖

3、track:

接收两个参数:target 和 key

如果没有 activeEffect,则说明没有创建 effect 依赖

如果有 activeEffect,则去判断 WeakMap 集合中是否有 target 属性,

WeakMap 集合中没有 target 属性,则 set(target, (depsMap = new Map()))

WeakMap 集合中有 target 属性,则判断 target 属性的 map 值的 depsMap 中是否有 key 属性

depsMap 中没有 key 属性,则 set(key, (dep = new Set()))

depsMap 中有 key 属性,则添加这个 activeEffect

4、trigger:

判断 WeakMap 中是否有 target 属性

WeakMap 中没有 target 属性,则没有 target 相应的依赖

WeakMap 中有 target 属性,则判断 target 属性的 map 值中是否有 key 属性,有的话循环触发收集的 effect()

[img]

Vue实现自动触发功能

button @click='toggle' v-triggertoggle/button

directives:{

    trigger:{

    inserted(el,binging){

        el.click()

 猜档     //$(el).trigger('click'春和)}  }}

页面加载的时候,点穗森乱击事件被执行了!

参考:

在vue.js中如何实现JQuery中的Event trigger?

使用事件修饰符就可以了,比你上面的代码还要简单一些。

假设消磨虚你要给一个input添加事件,游衫并且只能在按下回车时触发,可以这么写:

input :keydown.enter="evt"

意思是当按下enter键时,触发evt方法。

这个在官方文档里就有很详细的例子说明的,所有的拿燃按键都可以使用修饰符直接绑定,都不需要你判断是按了哪一个键。

Vue3.0采用新特性Proxy来实现数据状态的响应,它的原理是什么?

Vue3 使用了 Proxy 替换了原来的 Object.defineProperty 来实现数据响应。

很简单,直接Vue引入reactive方法,接收一个对象参数,就实现了数据的响应式:

reactive 内部的核心代码 简化 如下:

首先判断传入的参数类型是否可以用于观察,目前支持的类型为 Object|Array|Map|Set|WeakMap|WeakSet。

接下来判断参数的构造函数,根据类型获得不同的 handlers。这里我们就统一使用 baseHandlers ,因为这个已经覆盖 99% 的情况了。只有 Set, Map, WeakMap, WeakSet 才会使用到 collectionHandlers。

对于 baseHandlers 来说,最主要的是劫持了 get 和 set 行为,这两个行为同时也能原生劫持 数组下标修改值及对象新增属性的行为, 这一点非常重要,因为 Object.defineProperty 就不行。

最后就是构造一个 Proxy 对象完成数据的响应式。相比 Object.defineproperty 一开始就要 递归遍历整个对象 的做法来说,使用 Proxy 性能会好得多。比如原来 forEach 遍历:

接下来当我们去使用 state 对象的时候,就能劫持到内部的行为。

读取时:state.num 就会触发 get 函数;

修改时:state.num = 100 就会触发 set 函数。

以下是这两个函数的核心(TS语法):

对于 get 函数来说,获取值肯定薯配是最核心的一步骤了。接下来是调用 track,这个和 effect 有关,下文再说。最后是判断值的类型,如果是对象的话就继续包装成 Proxy。

对于 set 函数来说,设置值是第一步骤,然后调用 trigger,这也是 effect 中的内容。

简单来说,如果某个 effect 回调中有使用到 state.num,那么这个回调会被收集起来,并在调用 state.num =100 时触发。

那么怎么收集这些内容呢?这就要说说 targetMap 这个对象了。它用于存储依赖关系,类似以下结构,这个结构会在 effect 文件中被用到

先来解释下三者到底是什么,这个很重要 :

这里笔者把这些内容脱离源码串起来讲一下流程。

首先创建一个 Proxy 对象,targetMap 会把这个对象收集起来当做 key。

接下来调用 effect 回调的时候会把这个回调保存起来,用于下面的依赖收集。在调用的过程中会触发 counter 的 get 函数,内部调用了 track 函数,这个函数会使用到 targetMap。

这里首先通过 target 从 targetMap 中取到一个对象,这个对象也就是 target 所有的依赖关系。那么对于 counter.num 来说,num 就是这个对象的 key(这里如果有点模糊的话可以先看下上面的数据结构),值是一个依赖回调的集合,因为 counter.num 可能会被多个地方依赖到。

回调执行完毕以后会把保存的回调销毁掉。

当我们调用数腊指 counter.num = 7 时,触发 set 函数,内部调用 trigger 函数,同样会使用到 targetMap。

同样通过 target 取到一个对象,然后通过 key 也就是 num 去取出依赖集合,最后遍历这个集合执行里面所有的回调函数。

另外对于 computed 来说,内部也是使用到了 effect,无局野非它的回调不会在调用 effect 后立即执行,只有当触发 get 行为以后才会执行回调并进行依赖收集,举个例子:

对于以上代码来说,computed 的回调永远不会执行,只有当使用到了 cValue.value 时才会执行回调,然后接下来的操作就和上面的没区别了。

Vue 3.0 - track与trigger的容器

此文章为早期版本,可能与当前最新版本有出入,敬请等待更新~

开发过程中,缺枣晌key不只是岩饥String,有可能是symbol等等。详情点击 此处

track 主要集中为两个方向服务:

``javascript

export function trigger(

target: object,

type: TriggerOpTypes,

key?: unknown,

extraInfo?: DebuggerEventExtraInfo

) {

const depsMap = targetMap.get(target)

if (depsMap === void 0) {

// never been tracked

return

}

const effects = new SetReactiveEffect()

const computedRunners = new SetReactiveEffect()

if (type === TriggerOpTypes.CLEAR) {

// collection being cleared, trigger all effects for target

depsMap.forEach(dep = {

addRunners(effects, computedRunners, dep)

})

} else {

// schedule runs for SET | ADD | DELETE

if (key !== void 0) {

addRunners(effects, computedRunners, depsMap.get(key))

}

// also run for iteration key on ADD | DELETE

if (type === TriggerOpTypes.ADD || type === TriggerOpTypes.DELETE) {

const iterationKey = isArray(target) ? 'length' : ITERATE_KEY

addRunners(effects, computedRunners, depsMap.get(iterationKey))

}

}

const run = (effect: ReactiveEffect) = {

scheduleRun(effect, target, type, key, extraInfo)

}

// Important: computed effects must be run first so that computed getters

//伏锋 can be invalidated before any normal effects that depend on them are run.

computedRunners.forEach(run)

effects.forEach(run)

}

聊一聊 Vue3 中响应式原理

Vue.js 3.0 "One Piece" 正式发布已经有一段时间了,真可谓是千呼万唤始出来啊!

相比于 Vue2.x , Vue3.0 在新的版本中提供了更好的性能、更小的捆绑包体积、更好的 TypeScript 集成、用于处理大规模用例的新 API 。

在发布之前,尤大大就已经声明了响扒蠢应式方面将采用 Proxy 对于之前的 Object.defineProperty 进行改写。其主要目春扰陪的就是弥补 Object.defineProperty 自身的一些缺陷,例如无法检测到对象属性的新增或者删除,不能监听数组的变化等。

而 Vue3 采用了新的 Proxy 实现数据读取和设置拦截,不仅弥补了之前 Vue2 中 Object.defineProperty 的缺陷,同时也带来了性能上的提升。

今天,我们就来盘一盘它,看看 Vue3 中响应式是如何实现的。

The Proxy object enables you to create a proxy for another object, which can intercept and redefine fundamental operations for that object. MDN

Proxy - 代理,顾名思义,就是在要访问的对象之前增加一个中间层,这样就不直接访问对象,而是通过中间层做一个中转,通过操作代理对象,来实现修改目标对象。

关于 Proxy 的更多的知识,可以参考我之前的一篇文章 —— 初探 Vue3.0 中的一大亮点——Proxy ! ,这里我就不在赘述。

Vue3 中响应式核心方法就是 reactive 和 effect , 其中 reactive 方法是负责将数据变成响应式, effect 方法的作用是根据数据变化去更新视图或调用函数,与 react 中的 useEffect 有点类似~

其大概用法如下:

默认会执行一次,打印 Hello , 之后更改了 data.name 的值后,会在触发执行一次,打印 World 。

我们先看看 reactive 方法的实现~

reactive.js

首先应该明确,我们应该导出一个 reactive 方法,该方法有一个参数 target ,目的就是将 target 变成响应式李枝对象,因此返回值就是一个响应式对象。

reactive 方法基本结构就是如此,给定一个对象,返回一个响应式对象。

其中 isObject 方法用于判断是否是对象,不是对象不需要代理,直接返回即可。

reactive 方法的重点是 Proxy 的第二个参数 handler ,它承载监控对象变化,依赖收集,视图更新等各项重大责任,我们重点来研究这个对象。

handler.js

在 Vue3 中 Proxy 的 handler 主要设置了 get , set , deleteProperty , has , ownKeys 这些属性,即拦截了对象的读取,设置,删除, in 以及 Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法。

这里我们偷个懒,暂时就考虑 set 和 get 操作。

handler.get()

get 获取属性比较简单,我们先来看看这个,这里我们用一个方法创建 getHanlder 。

这里推荐使用了 Reflect.get 而并非 target[key] 。

可以发现, Vue3 是在取值的时候才去递归遍历属性的,而非 Vue2 中一开始就递归 data 给每个属性添加 Watcher ,这也是 Vue3 性能提升之一。

handler.set()

同理 set 操作,我们也是用一个方法创建 setHandler 。

Reflect.set 会返回一个 Boolean 值,用于判断属性是否设置成功。

完事后将 handler 导出,然后在 reactive 中引入即可。

测试几组对象貌似没啥问题,其实是有一个坑,这个坑也跟数组有关。

如上例子,如果我们选择代理数组,在 setHandler 中打印其 key 和 value 的话会得到 3 4 , length 4 这两组值:

如果不作处理,那么会导致如果更新视图的话,则会触发两次,这肯定是不允许的,因此,我们需要将区分新增和修改这两种操作。

Vue3 中是通过判断 target 是否存在该属性来区分是新增还是修改操作,需要借助一个工具方法 —— hasOwnProperty 。

这里我们将上述的 createSetter 方法修改如下:

如此一来,我们调 push 方法的时候,就只会触发一次更新了,非常巧妙的避免了无意义的更新操作。

effect.js

光上述构造响应式对象并不能完成响应式的操作,我们还需要一个非常重要的方法 effect ,它会在初始化执行的时候存储跟其有关的数据依赖,当依赖数据发生变化的时候,则会再次触发 effect 传递的函数。

其基本雏形如下,入参是一个函数,还有个可选参数 options 方便后面计算属性等使用,暂时不考虑:

createReactiveEffect 就是为了将 fn 变成响应式函数,监控数据变化,执行 fn 函数,因此该函数是一个高阶函数。

createReactiveEffect 将原来的 fn 转变成一个 reactvieEffect , 并将当前的 effect 挂到全局的 activeEffect 上,目的是为了一会与当前所依赖的属性做好对应关系。

我们必须要将依赖属性构造成 { prop : [effect,effect] } 这种结构,才能保证依赖属性变化的时候,依次去触发与之相关的 effect ,因此,需要在 get 属性的时候,做属性的依赖收集,将属性与 effect 关联起来。

依赖收集 —— track

在获取对象的属性时,会触发 getHandler ,再次做属性的依赖收集,即 Vue2 中的发布订阅。

在 setHandler 中获取属性的时候,做一次 track(target, key) 操作。

整个 track 的数据结构大概是这样

目的就是将 target , key , effect 之间做好对应的关系映射。

打印 targetMap 的结构如下:

**触发更新 —— trigger **

上述已经完成了依赖收集,剩下就是监控数据变化,触发更新操作,即在 setHandler 中添加 trigger 触发操作。

这样一来,获取数据的时候通过 track 进行依赖收集,更新数据的时候再通过 trigger 进行更新,就完成了整个数据的响应式操作。

再回头看看我们先前提到的例子:

控制台会依次打印 Hello ***** effect ***** 以及 World ***** effect ***** , 分别是首次渲染触发跟更新数据重渲染触发,至此功能实现!

整体来说, Vue3 相比于 Vue2 在很多方面都做了调整,数据的响应式只是冰山一角,但是可以看出尤大团队非常巧妙的利用了 Proxy 的特点以及 es6 的数据结构和方法。另外, Composition API 的模式跟 React 在某些程度上有异曲同工之妙,这种设计模式让我们在实际开发使用中更加的方法快捷,值得我们去学习,加油!

最后附上仓库地址 github ,欢迎各位大佬批评斧正~

关于vuetrigger和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

标签列表