掘金文章归档 · 第 20 篇 Vue3 / Vite 系列 3/4 Vue.js 基础

vue3 新特性 / 新用法 / 新写法及注意点

watch / watchEffect 的区别与用法,getCurrentInstance proxy 获取路由列表

原文作者:随意_(掘金) | juejin.cn/post/7033702981828788232 | 发布于 2021-11-23 | 阅读 296 · 约 1 分钟

1watch / watchEffect

watch 监听 ref 及 reactive 的区别,二者具体用法如下。

监听 ref

watch(state, (newValue, oldValue) => {
  console.log(`原值为${oldValue}`)
  console.log(`新值为${newValue}`)
})

监听 reactive

const state = reactive({ count: 0 })
watch(() => state.count, (newValue, oldValue) => {
  console.log(`原值为${oldValue}`)
  console.log(`新值为${newValue}`)
})
⚠️ 注意:reactive 对象不能直接监听,需要以回调函数返回的形式(() => state.count)才能正确拿到 newValue / oldValue。

watchEffect

const state = reactive({ count: 0, name: 'zs' })
watchEffect(() => {
  console.log(state.count)
  console.log(state.name)
})

何时使用 watch、watchEffect,二者区别

API特点适用场景
watch可监听 ref 及 reactive 的值,可自由配置(deep / immediate),默认第一次不触发需要监听变化前及变化后的值,用法相对繁琐
watchEffect初始化时自动查找内部依赖的变量,内部任何一值更改都会触发回调,但不会返回修改前及修改后的数据只需在依赖变化时执行副作用,无需拿新旧值
// watch 典型用法:deep + immediate 配置
watch(
  symbolDataList,
  newVal => {
    if (!newVal.length) return;
    symbolDataListObjData.symbolDataList = [...newVal];
  },
  {
    deep: true,
    immediate: true
  }
);
// watchEffect 典型用法:自动收集依赖
watchEffect(() => {
  console.log(state.count)
  console.log(state.name)
})
📌 核心差异一句话:watch 需要显式声明监听目标、能拿到新旧值;watchEffect 自动收集依赖、拿不到前后值,但写法更简洁。

2getCurrentInstance proxy

由于 vue3 不会提供 this 选项,在处理路由时会获取当前的路由列表,可如下操作:

import { defineComponent, onMounted, ref, watch, getCurrentInstance } from "vue";

const { proxy } = getCurrentInstance()!;
const routeList = proxy?.$router.getRoutes() || [];
routeList.forEach(item => {
  if (item.meta.menu && item.children && item.children.length > 0) {
    item.children = item.children.filter(sonItem => {
      return !sonItem.meta?.hidden;
    });
    menuList.value.push(item);
  }
});
⚠️ 注意点:getCurrentInstance() 只能在 setup 或生命周期钩子中调用;通过 proxy 可以访问 $router$route 等全局实例属性,弥补 vue3 无 this 的写法差异。