自己做网站卖能赚钱吗,拓展公司,ps制作网页主页效果图,苏州seo服务watch和watchEffect是Vue 3.0中新增的两个响应式API#xff0c;用于监听数据的变化。watch适用于需要获取新值和旧值#xff0c;或者需要懒执行的场景#xff0c;而watchEffect适用于需要监听多个数据源#xff0c;并且需要立即执行的场景。它们之间的区别如下#xff1a;… watch和watchEffect是Vue 3.0中新增的两个响应式API用于监听数据的变化。watch适用于需要获取新值和旧值或者需要懒执行的场景而watchEffect适用于需要监听多个数据源并且需要立即执行的场景。它们之间的区别如下 watch是监听单个数据源可以设置immediate和deep选项可以获取新值和旧值watchEffect则是监听一组数据源不能设置immediate和deep选项不能获取新值和旧值。watch是懒执行的只有在数据变化时才会执行回调函数而watchEffect则是立即执行的不管数据是否变化。watch可以监听计算属性而watchEffect不能监听计算属性。 watch和watchEffect用法区别
watch和watchEffect在使用上也有一些区别具体如下
watch的使用方法
watch(source, callback, options)其中source可以是一个响应式数据源也可以是一个函数返回一个响应式数据源。callback是回调函数会在数据变化时执行可以获取新值和旧值。options是一个对象可以设置immediate和deep等选项。 watch使用示例
import { ref, watch} from vueconst count ref(0)// 使用watch监听数据变化并在下一次DOM更新前执行回调函数
watch(count, (newVal, oldVal) {console.log(count变化了, newVal, oldVal)
}, {flush: pre
})// 修改数据
count.valuewatchEffect的使用方法
watchEffect(callback, options)其中callback是一个函数会在组件渲染时执行并且会在数据变化时重新执行。options是一个对象可以设置flush选项。 需要注意的是watchEffect的回调函数中可以直接使用响应式数据源不需要显式获取新值和旧值因为watchEffect会自动收集依赖在数据变化时重新执行回调函数。 watchEffect示例
import { ref, watchEffect } from vueconst count ref(0)// 使用watchEffect监听数据变化默认在下一次DOM更新后执行回调函数
watchEffect(() {console.log(count2变化了, count.value)
})// 修改数据
count.value源码分析 watch和watchEffect相关源码都在core-main\packages\runtime-core\src\apiWatch.ts文件中 watchEffect方法 在源码里watchEffect是一个函数接收两个参数第一个是effect也就是用户传入的执行函数。第二个是options设置flush属性flush属性表示回调函数的执行时机。默认 flush 选项是 pre即在依赖变化之后立即执行副作用函数。 watchEffect内部调用了doWatch方法doWatch方法接收三个参数watchEffect在调用的doWatch时候将第二个参数设为null 。这里是重点为什么因为等下看watch实现的时候就知道了watch也调用了doWatch方法。只不过第二个参数不为null了。watchEffect先看到这你就记住要去调doWatch方法。接下来去看doWatch怎么实现的。 flush具体有以下几个选项 pre在下一次 DOM 更新前执行回调函数默认选项。post在下一次 DOM 更新后执行回调函数。sync立即执行回调函数。 watchPostEffect和watchSyncEffect 方法 值得注意的是这个watchEffect方法下面还对外抛出了两个方法watchPostEffect和watchSyncEffect。前面说了通过flush属性控制effect执行的时机watchEffect默认是flush:preDOM 更新前执行。如果你想改变flush除了在watchEffect改变flush的值还可以直接调watchPostEffect和watchSyncEffect方法。 watch方法 在源码里watch是一个函数接收三个参数第一个是source也就是用户的要监听的属性。第二个是回调函数通常使用箭头函数监听新旧值的变化并执行内部的方法。第三个是options可以设置flush\immediate\deep\once属性。默认 flush 选项也是 pre即在依赖变化之后立即执行副作用函数。 watch内部也调用了doWatch方法doWatch方法接收watch传入的三个参数。 核心doWatch方法 从前面的分析可以看到watchEffect和watch都执行了doWatch方法。唯一不同的是watchEffect使用doWatch时第二个参数使用的是null。那么看下doWatch的执行逻辑吧 doWatch接收的参数 doWatch方法接收三个参数source、cb、options。具体解释如下 souce要监听的数据源可以是一个 ref 对象、一个 reactive 对象、一个数组或一个函数。 cb是回调函数在watch中使用。(newValue,oldValue){}。 options是一个配置对象接收以下属性 deep是否深度监听默认值为 false。如果设置为 true则会递归地监听 source 对象的所有属性和子属性。immediate是否立即执行回调函数默认值为 false。如果设置为 true则会在监听器被创建时立即执行一次回调函ctions。flush指定回调函数的刷新时机可以是 pre、post 或 sync默认值为 pre。onTrack一个函数用于在追踪依赖时调用。onTrigger一个函数用于在触发依赖时调用。 getter 函数——获取监听数据执行结果 doWatch方法第一个核心是定义一个getter函数用于获取需要监听的数据。getter 的值是根据 source 的不同类型而得到。 如果 source 是一个 ref 对象那么 getter 返回 source.value。如果 source 是一个 reactive 对象那么 getter 返回 reactiveGetter(source)。如果 source 是一个数组那么 getter返回一个数组其中每个元素是一个值或一个函数的执行结果。具体来说如果数组中的某个元素是一个 ref 对象那么返回 s.value如果是一个 reactive 对象那么返回 reactiveGetter(s)如果是一个函数那么返回 callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER)。如果 source 是一个函数那么 getter 的值取决于 cb 的值 如果 cb 存在那么 getter 的值是一个函数返回 callWithErrorHandling(source, instance, ErrorCodes.WATCH_GETTER)。否则没有cbgetter 的值是一个函数返回一个值或一个函数的执行结果。也就是watchEffect具体来说如果 cleanup 存在那么首先执行 cleanup()然后返回 callWithAsyncErrorHandling(source, instance, ErrorCodes.WATCH_CALLBACK, [onCleanup])。 effect——响应式数据依赖管理 doWatch 的第二个关键是通过new Reactive()创建一个effect实例。接收getter、NOOP、scheduler。getter是一个函数根据source不同返回一个值或一个函数的执行结果。NOOP是一个空的箭头函数。scheduler是任务job的调度器默认flush:pre走的是queueJob任务队列调度器通过队列管理任务先进先出。 这个effect是什么scheduler是什么queueJob(job)又是什么呢接着看源码 ReactiveEffect作用——依赖收集 这个ReactiveEffect是实现vue3响应式数据更新的核心类。当数据变化时可以通过 trigger 函数触发所有依赖该数据的效果从而更新相关的视图。reactiveEffect 类的作用包括 构造函数接受四个参数分别是用于执行的函数 fn、触发更新的函数 trigger、可选的调度器函数 scheduler 和可选的效果作用域 scope。dirty 属性一个只读属性表示当前的脏标记可以是 DirtyLevels.NotDirty、DirtyLevels.Dirty、DirtyLevels.MaybeDirty 或 DirtyLevels.QueryingDirty 之一。run 方法执行当前效果即调用 fn 函数并在执行前后进行一些必要的操作如更新脏标记、记录活跃的效果等。stop 方法停止当前效果即取消对 fn 函数的依赖并进行一些必要的清理操作。 调度器scheduler——管理job的工具 Vue 3 中的 scheduler.ts 文件是用来实现调度器scheduler功能的。调度器在 Vue 中负责管理异步更新的调度和执行确保在适当的时机更新组件以及处理副作用函数。具体来说scheduler.ts 文件包含了以下主要功能 调度更新调度器负责管理组件的更新调度根据更新的优先级和策略来决定何时执行更新操作以提高性能和效率。 异步更新调度器可以将更新操作异步执行通过微任务或宏任务来延迟更新操作以避免阻塞主线程提高页面的响应性。 副作用函数的调度调度器还负责管理副作用函数的执行时机根据副作用函数的依赖关系和执行策略来调度副作用函数的执行。 性能优化调度器可以根据具体情况对更新操作进行优化比如批量更新、合并更新等操作以减少不必要的更新和提高性能。 queueJob 函数来判断当前任务是否已存在于任务队列中如果不存在则将当前任务插入到任务队列中。当任务队列中的任务数量达到一定的阈值时scheduler 函数会通过 queueFlush 函数来执行任务队列中的任务。 watch和watchEffect的核心区别——job函数做了什么 前面经过分析doWatch拿到了三个参数source,cb,options然后根据source的不同定义了一个getter函数得到了监听数据的执行结果。然后又定义了一个effect管理依赖收集通过effect的dirty判断依赖的属性有没有变化effect的run方法可以运行接收的第一个fn函数在这里fn是getter函数。effect还有一个调度器函数默认是queueJob(job)。queueJob用来管理一个任务队列。核心方法是看单个job是怎么实现的。 job的定义还是在doWatch方法内可以看到job先是对effect的active和dirty进行判断如果都不满足不需要重新执行方法。 接着判断cb也就是doWatch接收的第二个参数。还记得吗watch调用doWatch的时候第二个参数是回调函数(newValue,oldValue){}而watchEffect调用的时候第二个参数传的是null。在这里可以看到watch和watchEffect的区别了 如果cb存在先去执行effect.run()方法得到返回值给newValue,然后将newValue和oldValue拿到执行回调方法cb 如果cb不存在直接执行effect的run方法 可以看到watchEffect就少了一步就是它不需要去处理新值和旧值的逻辑如果在依赖的数据发生变化的时候你必须想知道是哪个数据变化并且旧值和新值的比较关系那么你就用watch如果你不关心旧值也不关心是哪个数据项变化你就用watchEffect。在doWatch里会将watchEffect的第一个参数当成getter,在effect执行run的时候去执行getter也就是你传入watchEffect的函数。 总结 在这部分源码分析中用了很长的篇幅取介绍doWatch的实现因为watch和watchEffect都调用了doWatch只是第二个参数不同watchEffect传入的是nullwatch传入的是cb。 doWatch干了什么事情呢 首先由要收集数据依赖收集的是哪写属性呢 source传入的可能是ref\reactive属性、数组或者函数这个时候需要对source进行计算看最终依赖的是什么东西通过定义一个getter函数根据source类型不同得到监听数据最后的执行结果。 怎么收集数据依赖呢 使用ReactiveEffect类定义一个effect实例将前面定义的getter传进去通过操作effect的run方法执行getter通过effect的dirty属性判断getter是否改变。 数据改变了doWatch怎么做呢 数据发生变化了也就是effect的dirty属性或者active属性有一个为true了。这时doWatch根据传入的第二个参数cb是否有值进行判断。 如果cb有值那就是watch方法watch是不是想知道依赖的getter发生变化后得到的新值和之前的旧值啊所以cb有值的时候先去执行effect的run方法得到依赖属性变化后的新值newValue将newValue和oldValue传入cb执行cb回调方法。 如果cb没值那就是watchEffect方法。直接去执行effect的run方法将传入的source转换为getter执行就好了。 总的来说 watch vs watchEffect watch 用于需要知道是哪个数据项发生变化以及需要比较旧值和新值的情况因为它提供了旧值和新值的参数。而 watchEffect 则更适合在不关心旧值和具体数据项变化的情况下使用因为它只关注副作用函数的执行不提供旧值和新值的参数。 看到这里如果你已经稍微理解watch和watchEffect的区别了请一键三连哦~