Skip to content

应用实例

每个 Vue 应用都是通过 createApp 函数创建一个新的应用实例开始的。

创建应用实例

javascript
import { createApp } from 'vue'

const app = createApp({
  /* 根组件选项 */
})

根组件

我们传入 createApp 的对象实际上是一个组件,每个应用都需要一个"根组件",其他组件将作为其子组件。

javascript
import { createApp } from 'vue'
// 从一个单文件组件中导入根组件
import App from './App.vue'

const app = createApp(App)

如果你使用的是单文件组件,我们可以直接从另一个文件中导入根组件。

挂载应用

应用实例必须在调用了 .mount() 方法后才会渲染出来。该方法接收一个"容器"参数,可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串:

html
<div id="app"></div>
javascript
app.mount('#app')

应用根组件的内容将会被渲染在容器元素里面。容器元素自己将不会被视为应用的一部分。

.mount() 方法应该始终在整个应用配置和资源注册完成后被调用。同时请注意,不同于其他资源注册方法,它的返回值是根组件实例而非应用实例。

应用配置

应用实例会暴露一个 .config 对象允许我们配置一些应用级的选项,例如定义一个应用级的错误处理器,用来捕获所有子组件上的错误:

javascript
app.config.errorHandler = (err) => {
  /* 处理错误 */
}

应用实例还提供了一些方法来注册应用范围内可用的资源,例如注册一个组件:

javascript
app.component('TodoDeleteButton', TodoDeleteButton)

这使得 TodoDeleteButton 在应用的任何地方都是可用的。

多个应用实例

应用实例并不只限于一个。createApp API 允许你在同一个页面中创建多个共存的 Vue 应用,而且每个应用都拥有自己的用于配置和全局资源的作用域。

javascript
const app1 = createApp({
  /* ... */
})
app1.mount('#container-1')

const app2 = createApp({
  /* ... */
})
app2.mount('#container-2')

如果你正在使用 Vue 来增强服务端渲染 HTML,并且只想要 Vue 去控制一个大型页面中特定的一小部分,应避免将一个单独的 Vue 应用实例挂载到整个页面上,而是应该创建多个小的应用实例,将它们分别挂载到所需的元素上去。

完整示例

基本示例

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue 应用实例</title>
</head>
<body>
  <div id="app">
    <h1>{{ message }}</h1>
    <button @click="changeMessage">改变消息</button>
  </div>

  <script src="https://unpkg.com/vue@next/dist/vue.global.js"></script>
  <script>
    const { createApp } = Vue
    
    const app = createApp({
      data() {
        return {
          message: 'Hello Vue!'
        }
      },
      methods: {
        changeMessage() {
          this.message = this.message === 'Hello Vue!' 
            ? 'Hello World!' 
            : 'Hello Vue!'
        }
      }
    })
    
    app.mount('#app')
  </script>
</body>
</html>

使用单文件组件

javascript
// main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

// 全局配置
app.config.globalProperties.$http = axios
app.config.errorHandler = (err) => {
  console.error('全局错误:', err)
}

// 注册全局组件
app.component('MyButton', {
  template: '<button><slot></slot></button>'
})

// 挂载应用
app.mount('#app')
vue
<!-- App.vue -->
<template>
  <div id="app">
    <header>
      <h1>{{ title }}</h1>
    </header>
    <main>
      <Counter />
      <UserList />
    </main>
  </div>
</template>

<script>
import Counter from './components/Counter.vue'
import UserList from './components/UserList.vue'

export default {
  name: 'App',
  components: {
    Counter,
    UserList
  },
  data() {
    return {
      title: '我的 Vue 应用'
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}
</style>

应用级配置选项

errorHandler

用于为应用内抛出的未捕获错误指定一个全局处理函数。

javascript
app.config.errorHandler = (err, instance, info) => {
  // 处理错误,例如:报告给一个服务
  console.error('错误:', err)
  console.error('组件实例:', instance)
  console.error('错误信息:', info)
}

globalProperties

添加一个可以在应用的任何组件实例中访问的全局属性。

javascript
app.config.globalProperties.$http = axios
app.config.globalProperties.$translate = (key) => {
  // 翻译逻辑
}

在组件中使用:

javascript
export default {
  mounted() {
    this.$http.get('/api/users').then(response => {
      // 处理响应
    })
  }
}

performance

设置为 true 以在浏览器开发工具的性能/时间线面板中启用对组件初始化、编译、渲染和打补丁的性能追踪。

javascript
app.config.performance = true

应用 API

component()

注册或检索全局组件。

javascript
// 注册组件
app.component('MyComponent', {
  template: '<div>A custom component!</div>'
})

// 检索组件
const MyComponent = app.component('MyComponent')

directive()

注册或检索全局指令。

javascript
// 注册指令
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

// 检索指令
const focusDirective = app.directive('focus')

use()

安装 Vue.js 插件。

javascript
import router from './router'
import store from './store'

app.use(router)
app.use(store)

mixin()

应用一个全局 mixin。

javascript
app.mixin({
  created() {
    console.log('全局 mixin 被调用')
  }
})

provide()

提供一个值,可以在应用中的所有后代组件中注入使用。

javascript
app.provide('message', 'hello!')

在组件中注入:

javascript
export default {
  inject: ['message'],
  created() {
    console.log(this.message) // 'hello!'
  }
}

生命周期

应用实例的生命周期与组件生命周期不同。应用实例主要关注的是创建、配置和挂载的过程。

javascript
// 1. 创建应用实例
const app = createApp(App)

// 2. 配置应用
app.config.globalProperties.$api = api
app.use(router)
app.use(store)

// 3. 挂载应用
const vm = app.mount('#app')

// 4. 应用运行中...

// 5. 卸载应用(如果需要)
// app.unmount()

最佳实践

1. 应用配置集中管理

javascript
// config/app.js
export function configureApp(app) {
  // 全局属性
  app.config.globalProperties.$http = axios
  
  // 错误处理
  app.config.errorHandler = (err) => {
    console.error('应用错误:', err)
  }
  
  // 性能监控(仅开发环境)
  if (process.env.NODE_ENV === 'development') {
    app.config.performance = true
  }
}

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { configureApp } from './config/app'

const app = createApp(App)
configureApp(app)
app.mount('#app')

2. 插件注册

javascript
// plugins/index.js
import router from '../router'
import store from '../store'
import i18n from '../i18n'

export function registerPlugins(app) {
  app.use(router)
  app.use(store)
  app.use(i18n)
}

3. 全局组件注册

javascript
// components/global.js
import BaseButton from './BaseButton.vue'
import BaseInput from './BaseInput.vue'
import BaseModal from './BaseModal.vue'

export function registerGlobalComponents(app) {
  app.component('BaseButton', BaseButton)
  app.component('BaseInput', BaseInput)
  app.component('BaseModal', BaseModal)
}

下一步

现在你已经了解了如何创建和配置 Vue 应用实例,让我们继续学习:

应用实例是 Vue 应用的基础,掌握它将帮助你更好地组织和管理你的应用!

基于 Vue.js 官方文档构建的学习宝典