vue3中的watch的使用

317 阅读2分钟

1.什么是watch监听器

在 Vue 3 中,watch 主要用于组合式 API 中配合 refreactive 创建的响应式数据。watch 可以帮助我们在数据发生变化时执行副作用操作,比如发起 API 请求、修改其他状态或执行某些计算等。

2.基本用法

watch 主要接受两个参数:

  1. 第一个参数:要监听的响应式数据。
  2. 第二个参数:当第一个参数变化时执行的回调函数。

举个例子:

<script setup>
import { ref, watch } from 'vue'

// 定义响应式数据
const message = ref('')

// 使用 watch 监听 message 的变化
watch(message, (newValue, oldValue) => {
  console.log(`Message changed from "${oldValue}" to "${newValue}"`)
})
</script>

<template>
  <div>
    <input v-model="message" placeholder="Enter something"/>
    <p>{{ message }}</p>
  </div>
</template>

在上面的例子中:

  • message 是一个响应式的数据。
  • 回调函数有两个参数:newValueoldValue,分别表示数据的新值和旧值。

如果回调函数的参数只写一个,代表新值,比如:

image.png

image.png

3.使用场景

这个是我最关心
vue3官方文档这样写道:

image.png 比如,在个人博客项目中,我通过watch来监听主页面的主题切换情况,跟着切换markdown编辑器的主题。
因为这个markdown编辑器默认是可以切换明暗模式的:

image.png 问题来了,为什么要监听,直接把adminStore.theme给编辑器主题editorTheme不好吗?
直接将 adminStore.theme 赋值给 editorTheme 是不够灵活的,因为你无法控制 editorTheme 的初始值,且它会一直同步更新。

通过 watch,你可以控制 editorTheme 的初始值,以及在 adminStore.theme 变化时如何更新 editorTheme。同时,可以在变化时为 editorTheme 提供一个合理的默认值,比如 'light',以避免 adminStore.themenullundefined 时出现问题。


但是,注意:这个代码中的第一个参数是() => adminStore.theme,为什么不直接写adminStore.theme呢?

  • adminStore 本身是一个响应式对象,用pinia定义的:
export const useAdminStore = defineStore(
  'blog-front-ultimate',
  () => {
    const token = ref('')
    const admin = ref({})
    const theme = ref('')

    const setToken = (newToken) => {
      token.value = newToken
    }
    const removeToken = () => {
      token.value = ''
    }

    const getAdmin = async () => {
      const result = await adminGetInfoService()
      admin.value = result.data
    }

    //清除用户信息
    const setAdmin = (obj) => {
      admin.value = obj
    }

    const setTheme = (newTheme) => {
      theme.value = newTheme
    }

    const getTheme = () => {
      return theme.value
    }

    return {
      token,
      setToken,
      removeToken,
      admin,
      getAdmin,
      setAdmin,
      theme,
      setTheme,
      getTheme,
    }
  },
  {
    persist: true,
  },
)

但是,Vue 的 watch 不会自动深度监听对象的某个属性值(如 adminStore.theme),因为它的属性 theme 并不是直接的响应式对象,而是嵌套在一个响应式对象中。
用函数访问属性:

watch(() => adminStore.theme, (newTheme) => {
  console.log(`Theme changed to ${newTheme}`);
});

通过 () => adminStore.theme,我们明确告诉 watch,需要监听的是 adminStore.theme 的值。
但是,我还是不明白,为什么用箭头函数,vue就可以监听到adminStore.theme😁,算了,越挖越深了,就这样吧。