likes
comments
collection
share

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

作者站长头像
站长
· 阅读数 13

背景

下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:“请解释Vue.js中的Computed与Watch,并给出示例。”我心想,这面试官也太会玩了,这不是明摆着考验面试者对Vue.js的掌握程度嘛。

(当然,我肯定不会说自己忘了,于是开始连夜恶补一番。)

Computed

// 前置数据
const fristName = ref('ha');
const lastName = ref('kwan');

1. 创建一个只读的computed Ref

创建只读的Ref可以使用回调函数(getter函数)的形式

<template>
  {{ multName }}
  <button @click="multName = 'aaabbb'">change multName</button>
</template>

<script setup lang="ts">
  const multName = computed(() => fristName.value + ':' + lastName.value);
</script>

当点击按钮时,会发现视图并未改变

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

// read-only
function computed<T>(
  getter: (oldValue: T | undefined) => T,
  // see "Computed Debugging" link below
  debuggerOptions?: DebuggerOptions
): Readonly<Ref<Readonly<T>>>

2.创建一个可读可写的computed Ref

使用对象的形式,并传入getter函数和setter函数(二者皆必须)

<template>
  <div>{{ name }}</div>
  <button @click="name = 'aaa:bbb'">change name</button>
  {{ fristName }}---{{ lastName }}
</template>

<script setup lang="ts">
const name = computed({
  get() {
      // 渲染
    return fristName.value + ':' + lastName.value;
  },
  set(newVal) {
      // 点击按钮赋值
    [fristName.value, lastName.value] = newVal.split(':');
  }
});
</script>

当点击按钮时,视图发生改变

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

// writable
function computed<T>(
  options: {
    get: (oldValue: T | undefined) => T
    set: (value: T) => void
  },
  debuggerOptions?: DebuggerOptions
): Ref<T>

watch

1.使用watch侦听ref基本类型

<template>
  <button
    @click="
      () => {
        fristName = '我爱';
        lastName = '中华';
      }
    "
  >
    change name
  </button>
  {{ fristName }}---{{ lastName }}
</template>

<script setup lang="ts">
import { watch, computed, ref } from 'vue';
const fristName = ref('ha');
const lastName = ref('kwan');

watch([fristName, lastName], (res) => {
  // 只要有一个改变就会执行
  console.log('watch', res);
});
</script>

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

监听基本类型的ref是可以侦听到新值和旧值的变化的

不需要开启第三个参数 { deep: true }

watch(
  [fristName, lastName],
  (newVal, oldVal) => {
    console.log('newVal', newVal);
    console.log('oldVal', oldVal);
  },
);

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

2. 使用watch侦听ref引用类型

如果不开启deep,则无法侦听到属性值的变化,但是开启deep后,无法区分新值和旧值

<template>
  <button @click="modifiedName">change name</button>
  {{ fristName.name }}---{{ lastName.name }}
</template>

<script setup lang="ts">
import { watch, computed, ref, reactive } from 'vue';
const fristName = ref({ name: 'ha' });
const lastName = ref({ name: 'kwan' });

watch(
  [fristName, lastName],
  (newVal, oldVal) => {
    console.log('newVal', newVal);
    console.log('oldVal', oldVal);
  },
  {
    deep: true
  }
);

const modifiedName = () => {
  fristName.value.name = '我爱';
  lastName.value.name = '中华';
};
</script>

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

3. watch 侦听reactive类型的值

reactive可以被深度侦听(无需手动开启deep,默认开启,但是属性的层级比较深的时候还是需要手动深度监听)

但是依然无法区分新值和旧值!

<template>
  <button @click="modifiedName">change name</button>
  {{ fristName.name }}---{{ lastName.name }}
</template>

<script setup lang="ts">
import { watch, computed, ref, reactive } from 'vue';
const fristName = reactive({ name: 'ha' });
const lastName = reactive({ name: 'kwan' });

watch([fristName, lastName], (newVal, oldVal) => {
  console.log('newVal', newVal);
  console.log('oldVal', oldVal);
});

const modifiedName = () => {
  fristName.name = '我爱';
  lastName.name = '中华';
};
</script>

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

使用getter函数侦听单一属性,可以区分新值和旧值

watch(
  () => fristName.name,
  (newVal, oldVal) => {
    console.log('newVal', newVal);
    console.log('oldVal', oldVal);
  }
);

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

watch(
  () => [fristName.name, lastName.name],
  (newVal, oldVal) => {
    console.log('newVal', newVal);
    console.log('oldVal', oldVal);
  }
);

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

watchEffect

watchEffect接受一个回调函数,并在回调函数运行期间,自动收集响应式数据依赖。当某个依赖发生变化时,会重新执行回调函数(清理函数运行时机同useEffect)

注意,回调函数中收集依赖的过程是同步的,异步请求应该放在最后
watchEffect(async (cleanUp) => {
    (a.value, b.value); // 如果有响应式数据依赖于某个异步函数,则可以提前收集依赖
    c.value = await fetchApi(); // 如果c是不变的,就可以不用提出去
    // do something with a, b;
} )
最后

本文只是简单举例了一下watch以及computed的使用和特性,希望能起到抛砖引玉的目的。

感谢朋友甩来的面试题

文章起名来自kimi(狗头)

vue3中的watch和computed钩子函数的使用下午朋友突然甩了几道面试题给我,我一看不禁笑出声来。题目是这样的:

转载自:https://juejin.cn/post/7418367838971756607
评论
请登录