vue - 全局 API 应用实例

Vue.js 的应用实例(App Instance)是整个 Vue 应用的核心入口,封装了应用的创建、配置、挂载、全局注册等核心能力。以下基于官方文档,按「实例创建」「核心实例方法」「全局注册方法」「依赖注入」「应用配置」五大模块对所有 API 进行结构化解析,包含类型定义、功能说明、使用示例及关键注意事项,同时优化格式避免排版错位。

一、应用实例创建

用于初始化 Vue 应用实例,提供基础运行环境,核心包含 2 个 API:

1. createApp()

  • 类型定义function createApp(rootComponent: Component, rootProps?: object): App
  • 功能说明:创建浏览器端应用实例,是所有 Vue 应用的起点。
  • 关键细节 & 示例
    • 第一个参数为根组件(可内联定义或导入),第二个参数为传递给根组件的 props(可选)。
    • 基础使用示例:
      import { createApp } from 'vue'
      import App from './App.vue'
      // 传入根组件 + 根组件 props
      const app = createApp(App, { title: 'Vue 应用' })
      

2. createSSRApp()

  • 类型定义:与 createApp() 完全一致
  • 功能说明:创建服务端渲染(SSR)模式的应用实例。
  • 关键细节 & 示例
    • 用法、参数与 createApp() 无区别,仅运行模式不同(用于 SSR 场景下激活现有 DOM)。
    • 基础使用示例:
      import { createSSRApp } from 'vue'
      const app = createSSRApp(App)
      

二、核心实例方法

用于应用的挂载、卸载、生命周期监听等核心操作,是应用运行的关键:

1. app.mount()

  • 类型定义interface App { mount(rootContainer: Element | string): ComponentPublicInstance }
  • 功能说明:将应用挂载到 DOM 容器,触发组件树的首次渲染。
  • 关键细节
    • 参数支持 DOM 元素(如 document.getElementById('app'))或 CSS 选择器(如 '#app')。
    • 一个应用实例仅能调用 1 次,且挂载后会替换容器内原有 DOM(无模板时使用容器 innerHTML 作为模板)。
    • SSR 模式下仅激活现有 DOM,不执行替换操作。
  • 示例
    // 挂载到 CSS 选择器(推荐方式)
    app.mount('#app')
    // 挂载到实际 DOM 元素
    app.mount(document.body.firstChild)
    

2. app.unmount()

  • 类型定义interface App { unmount(): void }
  • 功能说明:卸载已挂载的应用实例,清理相关资源。
  • 关键细节:执行时会触发组件树中所有组件的 onUnmounted 生命周期钩子。
  • 示例
    const app = createApp(App).mount('#app')
    // 手动卸载(如页面销毁、路由切换时)
    app.unmount()
    

3. app.onUnmount()

  • 类型定义interface App { onUnmount(callback: () => any): void }
  • 功能说明:注册应用卸载时的回调函数,用于清理全局资源。
  • 关键细节:回调函数在 app.unmount() 执行时触发,适合清理定时器、全局事件监听等。
  • 示例
    const timer = setInterval(() => console.log('tick'), 1000)
    app.onUnmount(() => {
      console.log('应用已卸载')
      clearInterval(timer) // 清理定时器
    })
    

4. app.version

  • 类型定义interface App { version: string }
  • 功能说明:获取当前应用使用的 Vue 版本号。
  • 关键细节:常用于插件的版本兼容判断,避免因版本差异导致功能异常。
  • 示例
    export default {
      install(app) {
        const [major] = app.version.split('.').map(Number)
        if (major < 3) {
          console.warn('该插件仅支持 Vue 3+ 版本')
        }
      }
    }
    

三、全局注册方法

用于注册全局可用的组件、指令、插件,作用于整个应用的所有组件:

1. app.component()

  • 类型定义
    • 查询组件:component(name: string): Component | undefined
    • 注册组件:component(name: string, component: Component): this
  • 功能说明:全局注册或查询组件,注册后所有组件无需导入即可直接使用。
  • 关键细节:组件名建议遵循 PascalCase 命名规范,使用时可转为 kebab-case 标签。
  • 示例
    // 注册全局组件
    app.component('MyButton', {
      template: '<button>全局按钮</button>'
    })
    // 查询已注册的组件
    const MyButton = app.component('MyButton')
    

2. app.directive()

  • 类型定义
    • 查询指令:directive(name: string): Directive | undefined
    • 注册指令:directive(name: string, directive: Directive): this
  • 功能说明:全局注册或查询自定义指令,用于直接操作 DOM 元素。
  • 关键细节:支持对象形式(含多个生命周期钩子)和函数形式(简化版,默认触发 mounted + updated)。
  • 示例
    // 注册对象形式的指令(含生命周期钩子)
    app.directive('focus', {
      mounted(el) { el.focus() } // 元素挂载后自动聚焦
    })
    // 注册函数形式的指令(简化版)
    app.directive('focus', (el) => el.focus())
    // 查询已注册的指令
    const focusDir = app.directive('focus')
    

3. app.use()

  • 类型定义interface App { use(plugin: Plugin, ...options: any[]): this }
  • 功能说明:安装 Vue 插件,扩展应用功能。
  • 关键细节
    • 插件可以是带 install() 方法的对象,也可以是直接作为 install() 的函数。
    • 同一插件多次调用仅会安装 1 次,避免重复注册。
  • 示例
    import VueRouter from 'vue-router'
    // 安装插件并传递可选配置
    app.use(VueRouter, { mode: 'history' })
    

4. app.mixin()

  • 类型定义interface App { mixin(mixin: ComponentOptions): this }
  • 功能说明:应用全局混入,将逻辑注入所有组件实例。
  • 关键细节
    • 仅为 Vue 2 兼容保留,不推荐在新应用中使用,建议用组合式函数替代。
    • 混入逻辑会作用于所有组件,易造成命名冲突和逻辑混乱。
  • 示例
    // 全局混入生命周期钩子(不推荐)
    app.mixin({
      created() {
        console.log('所有组件创建时都会执行此逻辑')
      }
    })
    

四、依赖注入(全局共享数据)

用于在应用层级共享数据,无需通过 props 逐层传递,支持跨层级组件访问:

1. app.provide()

  • 类型定义interface App { provide<T>(key: InjectionKey<T> | symbol | string, value: T): this }
  • 功能说明:提供全局可注入的值,所有后代组件均可通过 inject() 获取。
  • 关键细节:注入键支持字符串、Symbol 或类型化的 InjectionKey,推荐使用 Symbol 避免命名冲突。
  • 示例
    // 应用层级提供全局配置数据
    app.provide('appConfig', { apiBaseUrl: 'https://api.example.com' })
    

2. app.runWithContext()

  • 类型定义interface App { runWithContext<T>(fn: () => T): T }
  • 功能说明:(Vue 3.3+)在应用的注入上下文中执行回调函数。
  • 关键细节:解决无组件实例时(如全局函数、定时器)无法使用 inject() 的问题。
  • 示例
    import { inject } from 'vue'
    app.provide('userId', 1001)
    
    // 无组件实例时获取注入值
    const userId = app.runWithContext(() => {
      return inject('userId') // 成功获取:1001
    })
    

组件中使用注入值的方式

// 方式 1:组合式 API 中使用 inject()
import { inject } from 'vue'
export default {
  setup() {
    const appConfig = inject('appConfig')
    console.log(appConfig.apiBaseUrl) // 输出接口地址
  }
}

// 方式 2:选项式 API 中使用 inject 选项
export default {
  inject: ['appConfig'],
  created() {
    console.log(this.appConfig.apiBaseUrl)
  }
}

五、应用配置(app.config)

每个应用实例暴露 config 对象,用于配置应用的全局行为,所有配置需在 app.mount() 前设置:

5.1 错误与警告处理

(1)errorHandler

  • 类型定义(err: unknown, instance: ComponentPublicInstance | null, info: string) => void
  • 功能说明:全局未捕获错误处理器,捕获组件渲染、生命周期、事件处理器等场景的错误。
  • 示例
    app.config.errorHandler = (err, instance, info) => {
      // 上报错误到监控平台
      console.error('全局错误:', err, instance, info)
    }
    

(2)warnHandler

  • 类型定义(msg: string, instance: ComponentPublicInstance | null, trace: string) => void
  • 功能说明:全局警告处理器,自定义 Vue 运行时警告的处理逻辑(仅开发环境有效)。
  • 示例
    app.config.warnHandler = (msg, instance, trace) => {
      // 忽略特定警告,仅打印非废弃相关的警告
      if (!msg.includes('deprecated')) {
        console.warn('自定义警告:', msg, trace)
      }
    }
    

(3)throwUnhandledErrorInProduction

  • 类型定义boolean(默认 false
  • 功能说明:生产环境下强制抛出未处理的错误,便于监控服务捕获(默认仅打印到控制台)。
  • 示例
    app.config.throwUnhandledErrorInProduction = true
    

5.2 性能与编译配置

(1)performance

  • 类型定义boolean(默认 false
  • 功能说明:启用性能追踪,开发模式下在浏览器「性能/时间线」面板显示组件初始化、编译、渲染的耗时(需浏览器支持 performance.mark)。

(2)compilerOptions

  • 类型定义:对象(仅完整构建版 vue.js 可用)
  • 功能说明:自定义模板编译规则,核心子配置如下:
    1. isCustomElement: (tag: string) => boolean:识别原生自定义元素(如 <ion-button>)。
    2. whitespace: 'condense' | 'preserve':设置模板空格的处理方式(默认 condense 压缩空格)。
    3. delimiters: [string, string]:修改插值分隔符(默认 ['{{', '}}'])。
    4. comments: boolean(默认 false):生产环境是否保留 HTML 注释。
  • 示例
    // 识别所有 ion- 前缀的标签为原生自定义元素
    app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ion-')
    // 保留模板中的空格
    app.config.compilerOptions.whitespace = 'preserve'
    // 替换插值分隔符为 ES6 模板字符串风格
    app.config.compilerOptions.delimiters = ['${', '}']
    

5.3 全局属性与合并策略

(1)globalProperties

  • 类型定义Record<string, any>
  • 功能说明:注册全局属性,替代 Vue 2 中的 Vue.prototype
  • 关键细节:组件自身属性优先级高于全局属性,避免命名冲突。
  • 示例
    // 注册全局属性 $api
    app.config.globalProperties.$api = {
      getUser: () => fetch('/api/user')
    }
    // 组件中使用
    export default {
      mounted() {
        this.$api.getUser().then(res => console.log(res))
      }
    }
    

(2)optionMergeStrategies

  • 类型定义Record<string, (to: unknown, from: unknown) => any>
  • 功能说明:自定义组件选项的合并策略,处理组件、混入、继承中同名选项的合并逻辑。
  • 示例
    // 自定义 msg 选项的合并策略(拼接字符串)
    app.config.optionMergeStrategies.msg = (parent, child) => {
      return (parent || '') + (child || '')
    }
    // 组件中使用
    const app = createApp({
      msg: 'Vue',
      mixins: [{ msg: 'Hello ' }],
      mounted() {
        console.log(this.$options.msg) // 输出 "Hello Vue"
      }
    })
    

5.4 其他配置

(1)idPrefix

  • 类型定义string(默认 undefined
  • 功能说明:自定义 useId() 生成的 ID 前缀,避免多应用同页面时的 ID 冲突。
  • 示例
    app.config.idPrefix = 'app1-'
    // 组件中使用 useId()
    import { useId } from 'vue'
    const id = useId() // 生成 "app1-0"
    

六、核心总结

  1. 应用创建流程createApp() 初始化 → app.config 配置全局行为 → 全局注册组件/指令/插件 → app.mount() 挂载到 DOM。
  2. 全局与局部的区别app.component() 等方法注册的资源全局可用,组件内注册的资源仅局部有效。
  3. 避坑要点
    • app.mount() 仅能调用 1 次,不可重复挂载同一个应用实例。
    • 全局混入(app.mixin())尽量避免,优先使用组合式函数实现逻辑复用。
    • compilerOptions 仅完整构建版可用,工程化项目需通过 Vite/Vue CLI 等构建工具配置。
  4. 依赖注入app.provide() + inject() 是全局共享数据的优雅方式,适合传递配置、用户信息等,无需逐层传递 props。

所有 API 均基于 Vue 3 环境设计,部分功能(如 runWithContext)需 Vue 3.3+ 版本支持,实际使用时需注意版本兼容性。

posted @ 2025-12-12 21:01  【唐】三三  阅读(3)  评论(0)    收藏  举报