• 前端面试怎么总问watch和computed区别


     给大家推荐一个实用面试题库

    1、前端面试题库 (面试必备)            推荐:★★★★★

    地址:web前端面试题库

    在现代前端的面试中,vue和react是面试过程中基本必问的技术栈,其中在聊到Vue响应式话题时,watch和computed是面试官非常喜欢聊的主题,虽然watchcomputed它们都用于监听数据的变化,但它们在实现原理、使用场景和行为上有着显著的区别。本文将深入探讨watchcomputed的原理和区别,并提供一些面试过程中的建议。

    先了解下Vue 3响应式

    Vue 3使用了Proxy作为其底层响应式实现可以监听对象属性的变化并触发相应的更新。当你访问数据时,Vue会建立一个依赖关系,然后在数据发生变化时通知相关的依赖项,从而更新视图。在这个背景下,我们深入探讨watchcomputed的底层源码和使用上的区别。

    Watch

    watch选项允许你监听数据的变化并执行自定义的操作。它通常用于监视某个数据的变化并执行副作用,比如异步请求、打印日志或触发动画。当你创建一个watch属性时,Vue会建立一个响应式依赖关系,将该watch属性关联到你要监视的数据。当监视的数据发生变化时,Vue会通知相关的watch属性,触发其回调函数。这个回调函数会接收新值和旧值作为参数,你可以在其中执行所需的操作。

    源码分析

    相关文件:vue/src/runtime-core/apiWatch.tsvue/src/reactivity/src/effect.ts

    在Vue 3的源码中,watch的实现主要依赖于createWatcher函数和Watcher类。

    • createWatcher函数负责创建Watcher实例,并接收监视的数据、回调函数以及其他选项。
    • Watcher类是watch的核心,它建立了对监视数据的依赖,并在数据变化时触发回调函数。
    • Watcher的内部,依赖项追踪和回调触发是通过Vue的响应式系统实现的。当监视的数据发生变化时,Vue会检测到依赖关系,从而触发Watcher的回调。
    解读

    1、在vue/src/runtime-core/apiWatch.ts中,watch函数负责创建Watcher实例,如下所示:

    1. export function watch(
    2.   source: WatchSource,
    3.   cb: WatchCallback,
    4.   options?: WatchOptions
    5. ): WatchStopHandle {
    6.   // 创建一个watcher实例
    7.   const watcher = new Watcher(vm, source, cb, {
    8.     deep: options && options.deep,
    9.     flush: options && options.flush,
    10.     onTrack: options && options.onTrack,
    11.     onTrigger: options && options.onTrigger,
    12.   });
    13.   // ...
    14. }

    这段代码创建了一个Watcher实例,其中vm是Vue实例,source是要监视的数据,cb是回调函数,以及其他选项。

    2、Watcher的核心工作在vue/src/reactivity/src/effect.ts`中,其中包含了依赖项追踪和回调触发的逻辑。下面是一个简化的示例:

    1. class Watcher {
    2.   // ...
    3.   get() {
    4.     // 设置当前的watcher为活动watcher
    5.     pushTarget(this);
    6.     // 执行监视的数据,触发依赖项的收集
    7.     const value = this.getter.call(this.vmthis.vm);
    8.     // 恢复之前的watcher
    9.     popTarget();
    10.     return value;
    11.   }
    12.   update() {
    13.     // 触发回调函数,通知数据变化
    14.     this.run();
    15.   }
    16.   run() {
    17.     // 执行回调函数
    18.     const value = this.get();
    19.     if (value !== this.value || isObject(value) || this.deep) {
    20.       // 触发回调函数
    21.       this.cb(value, this.value);
    22.       this.value = value;
    23.     }
    24.   }
    25.   // ...
    26. }

    这段代码展示了Watcher的关键部分,包括get方法用于获取数据和触发依赖项追踪,以及updaterun方法用于触发回调函数。

    watch使用

    1. <script setup>
    2. import { ref, watch } from 'vue';
    3. const count = ref(0);
    4. const doubledCount = ref(0);
    5. const incrementCount = () => {
    6. count.value++;
    7. };
    8. watch(count, (newVal, oldVal) => {
    9. // 监听 count 的变化
    10. doubledCount.value = newVal * 2;
    11. });
    12. script>

    在这个示例中,我们使用