Skip to content

Vue 特殊 API

这里所谓特殊 API 是指这些 API 只能在 setup script 中使用。而不能在任意的自定义服务中随意使用。

defineProps

强制要求只能在 setup script 中使用

defineEmits

强制要求只能在 setup script 中使用

defineModel

强制要求只能在 setup script 中使用

defineExpose

强制要求只能在 setup script 中使用

defineOptions

强制要求只能在 setup script 中使用

defineSlots

强制要求只能在 setup script 中使用

useSlots

依赖 setupContext,否则抛出 warning 信息

useAttrs

依赖 setupContext,否则抛出 warning 信息

useModel()

依赖 setupContext,否则抛出 warning 信息

官方文档不推荐使用这个 API,应该优先使用 defineModel

useTemplateRef()

依赖 setupContext,否则抛出 warning 信息

useId()

依赖 setupContext,否则抛出 warning 信息

useRootService vs useAppService

如果是在多 vue app 实例的项目中,或者在服务器端渲染的项目中。建议使用 useAppService 代替 useRootService。

如果是 CSR 项目,且只有一个 vue app 实例,那么就可以无脑使用 useRootService,不用考虑 useAppService 的问题。

从 API 使用角度来看 useRootService 不依赖具体 vue app 实例,可以直接在任意地方使用。

但是 useAppService 需要依赖具体的 vue app 实例,所以需要考虑如何获取指定的 vue app 实例对象。

在 nuxtjs 项目中,可以通过useNuxtApp获取当前的 nuxtApp 实例,再通过nuxtApp.vueApp获取 vue app 实例。

其中useNuxtApp可以在这些地方直接使用:plugin, Nuxt hook, Nuxt middleware, or Vue setup function

vue 指令中访问 useAppService

ts
import { defineNuxtPlugin } from '#imports';
import authDirective from '~/directives/auth';

export default defineNuxtPlugin(nuxtApp => {
  nuxtApp.vueApp.directive('auth', authDirective(nuxtApp.vueApp));
});

实际上单纯在指令内部是不能直接访问到 vue app 实例的,目前可行的方案就是利用 js 闭包来访问 vue app 实例对象。

middleware 中访问 useAppService

ts
export default defineNuxtRouteMiddleware(async (to, from) => {
  const nuxtApp = useNuxtApp();
});

defineNuxtRouteMiddleware 中可以通过 useNuxtApp 获取 nuxtApp 对象

defineNuxtPlugin 内部访问 useAppService

ts
export default defineNuxtPlugin(nuxtApp => {
  // xxx
});

defineNuxtPlugin 中可以直接获取 nuxtApp

utils 工具方法中访问 useAppService

第 1 种方案是手动把 utils 方法转为 service,然后利用依赖注入能力直接注入想要的服务即可。

第 2 种方案则是需要集中管理 vue app 实例对象。

ts
let vueApp = null;
function setVueApp(app) {
  vueApp = app;
}
function getVueApp() {
  return vueApp;
}

这样只需要在合适的时机调用setVueApp方法初始化一下 vueApp 变量即可。后续就可以随时调用getVueApp获取 vueApp 实例了。