Search K
Appearance
Appearance
📊 SEO元描述:2024年最新Vue实例创建教程,详解createApp、应用配置、组件挂载、实例属性。包含完整Vue应用初始化示例,适合开发者掌握Vue实例管理技术。
核心关键词:Vue实例创建、createApp、Vue应用初始化、Vue实例配置、Vue组件挂载、前端Vue实例
长尾关键词:Vue实例怎么创建、createApp用法、Vue应用配置方法、Vue实例属性、Vue.js实例管理
通过本节Vue实例创建,你将系统性掌握:
Vue实例是什么?这是理解Vue.js应用架构的核心问题。Vue实例是Vue应用的根对象,负责管理组件树、响应式数据、生命周期等,也是Vue应用的入口和控制中心。
💡 设计理念:Vue 3的实例设计更加模块化和类型安全,支持多个独立的应用实例,避免了全局污染。
createApp方法是Vue 3中创建应用实例的标准方式,替代了Vue 2的全局Vue构造函数:
<template>
<div id="app">
<h1>Vue实例创建示例</h1>
<!-- 基础组件展示 -->
<div class="instance-demo">
<h2>应用实例信息</h2>
<div class="app-info">
<p><strong>应用版本:</strong>{{ appVersion }}</p>
<p><strong>实例ID:</strong>{{ instanceId }}</p>
<p><strong>挂载时间:</strong>{{ mountTime }}</p>
<p><strong>组件名称:</strong>{{ $options.name }}</p>
</div>
<!-- 全局属性访问 -->
<div class="global-properties">
<h3>全局属性访问</h3>
<p><strong>全局消息:</strong>{{ $globalMessage }}</p>
<p><strong>API基础URL:</strong>{{ $apiBaseUrl }}</p>
<p><strong>用户信息:</strong>{{ $currentUser.name }}</p>
</div>
<!-- 实例方法调用 -->
<div class="instance-methods">
<h3>实例方法</h3>
<button @click="showInstanceInfo">显示实例信息</button>
<button @click="updateGlobalData">更新全局数据</button>
<button @click="callGlobalMethod">调用全局方法</button>
</div>
<!-- 组件状态 -->
<div class="component-state">
<h3>组件状态</h3>
<p><strong>本地计数:</strong>{{ localCount }}</p>
<p><strong>全局计数:</strong>{{ $globalCount }}</p>
<button @click="incrementLocal">增加本地计数</button>
<button @click="incrementGlobal">增加全局计数</button>
</div>
</div>
<!-- 子组件示例 -->
<div class="child-components">
<h2>子组件实例</h2>
<ChildComponent ref="childRef" :message="parentMessage" />
<button @click="accessChildInstance">访问子组件实例</button>
</div>
<!-- 动态组件 -->
<div class="dynamic-components">
<h2>动态组件</h2>
<select v-model="currentComponent">
<option value="ComponentA">组件A</option>
<option value="ComponentB">组件B</option>
<option value="ComponentC">组件C</option>
</select>
<component :is="currentComponent" :key="componentKey" />
<button @click="recreateComponent">重新创建组件</button>
</div>
</div>
</template>
<script>
import { ref, getCurrentInstance, onMounted } from 'vue'
// 子组件定义
const ChildComponent = {
name: 'ChildComponent',
props: ['message'],
setup(props) {
const childData = ref('子组件数据')
const childMethod = () => {
alert('子组件方法被调用')
}
return {
childData,
childMethod
}
},
template: `
<div class="child-component">
<h4>子组件</h4>
<p>接收的消息: {{ message }}</p>
<p>子组件数据: {{ childData }}</p>
<button @click="childMethod">子组件方法</button>
</div>
`
}
// 动态组件定义
const ComponentA = {
name: 'ComponentA',
template: `
<div class="component-a">
<h4>组件A</h4>
<p>这是动态加载的组件A</p>
<p>创建时间: {{ createTime }}</p>
</div>
`,
setup() {
const createTime = ref(new Date().toLocaleTimeString())
return { createTime }
}
}
const ComponentB = {
name: 'ComponentB',
template: `
<div class="component-b">
<h4>组件B</h4>
<p>这是动态加载的组件B</p>
<p>随机数: {{ randomNumber }}</p>
</div>
`,
setup() {
const randomNumber = ref(Math.floor(Math.random() * 1000))
return { randomNumber }
}
}
const ComponentC = {
name: 'ComponentC',
template: `
<div class="component-c">
<h4>组件C</h4>
<p>这是动态加载的组件C</p>
<ul>
<li v-for="item in items" :key="item">{{ item }}</li>
</ul>
</div>
`,
setup() {
const items = ref(['项目1', '项目2', '项目3'])
return { items }
}
}
export default {
name: 'VueInstanceDemo',
components: {
ChildComponent,
ComponentA,
ComponentB,
ComponentC
},
setup() {
// 获取当前实例
const instance = getCurrentInstance()
// 响应式数据
const appVersion = ref('3.3.0')
const instanceId = ref('app-' + Math.random().toString(36).substr(2, 9))
const mountTime = ref('')
const localCount = ref(0)
const parentMessage = ref('来自父组件的消息')
const currentComponent = ref('ComponentA')
const componentKey = ref(0)
const childRef = ref(null)
// 生命周期
onMounted(() => {
mountTime.value = new Date().toLocaleString()
console.log('组件已挂载,实例信息:', instance)
})
// 方法
const showInstanceInfo = () => {
const info = {
组件名称: instance?.type.name,
实例ID: instanceId.value,
挂载元素: instance?.vnode.el,
父组件: instance?.parent?.type.name || '无',
子组件数量: Object.keys(instance?.refs || {}).length
}
console.log('实例信息:', info)
alert(JSON.stringify(info, null, 2))
}
const updateGlobalData = () => {
// 通过全局属性更新数据
const app = instance?.appContext.app
if (app) {
app.config.globalProperties.$globalMessage = '全局消息已更新: ' + new Date().toLocaleTimeString()
app.config.globalProperties.$globalCount++
}
}
const callGlobalMethod = () => {
// 调用全局方法
const app = instance?.appContext.app
if (app && app.config.globalProperties.$showNotification) {
app.config.globalProperties.$showNotification('这是一个全局通知')
}
}
const incrementLocal = () => {
localCount.value++
}
const incrementGlobal = () => {
const app = instance?.appContext.app
if (app) {
app.config.globalProperties.$globalCount++
}
}
const accessChildInstance = () => {
if (childRef.value) {
console.log('子组件实例:', childRef.value)
console.log('子组件数据:', childRef.value.childData)
childRef.value.childMethod()
}
}
const recreateComponent = () => {
componentKey.value++
}
return {
appVersion,
instanceId,
mountTime,
localCount,
parentMessage,
currentComponent,
componentKey,
childRef,
showInstanceInfo,
updateGlobalData,
callGlobalMethod,
incrementLocal,
incrementGlobal,
accessChildInstance,
recreateComponent
}
}
}
</script>
<style scoped>
.instance-demo {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.app-info,
.global-properties,
.instance-methods,
.component-state,
.child-components,
.dynamic-components {
margin: 30px 0;
padding: 20px;
border: 1px solid #e0e0e0;
border-radius: 8px;
background-color: #fafafa;
}
.app-info h3,
.global-properties h3,
.instance-methods h3,
.component-state h3,
.child-components h2,
.dynamic-components h2 {
margin-top: 0;
color: #42b983;
border-bottom: 2px solid #42b983;
padding-bottom: 10px;
}
.app-info p,
.global-properties p,
.component-state p {
margin: 10px 0;
padding: 8px;
background-color: white;
border-radius: 4px;
border-left: 4px solid #42b983;
}
.instance-methods button,
.component-state button,
.child-components button,
.dynamic-components button {
margin: 5px 10px 5px 0;
padding: 8px 16px;
border: 1px solid #42b983;
background-color: #42b983;
color: white;
border-radius: 4px;
cursor: pointer;
}
.instance-methods button:hover,
.component-state button:hover,
.child-components button:hover,
.dynamic-components button:hover {
background-color: #369870;
}
.child-component {
background-color: white;
padding: 15px;
border-radius: 8px;
border: 1px solid #ddd;
margin: 15px 0;
}
.child-component h4 {
margin-top: 0;
color: #666;
}
.component-a {
background-color: #e8f5e8;
padding: 15px;
border-radius: 8px;
border: 1px solid #4caf50;
margin: 15px 0;
}
.component-b {
background-color: #fff3e0;
padding: 15px;
border-radius: 8px;
border: 1px solid #ff9800;
margin: 15px 0;
}
.component-c {
background-color: #e3f2fd;
padding: 15px;
border-radius: 8px;
border: 1px solid #2196f3;
margin: 15px 0;
}
.dynamic-components select {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
margin-right: 15px;
background-color: white;
}
</style>Vue 2方式:
// Vue 2 - 全局构造函数
import Vue from 'vue'
new Vue({
el: '#app',
data: {
message: 'Hello Vue 2'
},
methods: {
greet() {
alert(this.message)
}
}
})
// 全局配置(影响所有实例)
Vue.config.productionTip = false
Vue.component('GlobalComponent', { /* ... */ })Vue 3方式:
// Vue 3 - 应用实例
import { createApp } from 'vue'
const app = createApp({
data() {
return {
message: 'Hello Vue 3'
}
},
methods: {
greet() {
alert(this.message)
}
}
})
// 应用级配置(只影响当前应用)
app.config.globalProperties.$apiUrl = 'https://api.example.com'
app.component('GlobalComponent', { /* ... */ })
app.mount('#app')应用实例配置允许你为整个应用设置全局的属性、组件、指令等:
// main.js - 完整的应用配置示例
import { createApp } from 'vue'
import App from './App.vue'
// 创建应用实例
const app = createApp(App)
// 全局属性配置
app.config.globalProperties.$apiBaseUrl = 'https://api.example.com'
app.config.globalProperties.$globalMessage = '欢迎使用Vue 3应用'
app.config.globalProperties.$currentUser = {
id: 1,
name: '张三',
role: 'admin'
}
app.config.globalProperties.$globalCount = 0
// 全局方法
app.config.globalProperties.$showNotification = (message) => {
alert(`通知: ${message}`)
}
app.config.globalProperties.$formatDate = (date) => {
return new Date(date).toLocaleDateString('zh-CN')
}
app.config.globalProperties.$request = async (url, options = {}) => {
const response = await fetch(app.config.globalProperties.$apiBaseUrl + url, {
headers: {
'Content-Type': 'application/json',
...options.headers
},
...options
})
return response.json()
}
// 全局组件注册
app.component('GlobalButton', {
props: ['type', 'size'],
template: `
<button :class="['btn', 'btn-' + type, 'btn-' + size]">
<slot></slot>
</button>
`
})
app.component('GlobalIcon', {
props: ['name'],
template: `<i :class="'icon-' + name"></i>`
})
// 全局指令注册
app.directive('focus', {
mounted(el) {
el.focus()
}
})
app.directive('highlight', {
mounted(el, binding) {
el.style.backgroundColor = binding.value || 'yellow'
},
updated(el, binding) {
el.style.backgroundColor = binding.value || 'yellow'
}
})
// 错误处理配置
app.config.errorHandler = (err, instance, info) => {
console.error('全局错误处理:', err, info)
// 可以发送错误到监控服务
}
// 警告处理配置(开发环境)
if (process.env.NODE_ENV === 'development') {
app.config.warnHandler = (msg, instance, trace) => {
console.warn('Vue警告:', msg, trace)
}
}
// 性能追踪(开发环境)
if (process.env.NODE_ENV === 'development') {
app.config.performance = true
}
// 挂载应用
app.mount('#app')
// 导出应用实例供其他模块使用
export default app应用配置的核心特点:
💼 最佳实践:将应用配置集中管理,使用环境变量控制不同环境的配置,合理使用全局属性避免命名冲突。
// 多实例管理示例
class VueAppManager {
constructor() {
this.apps = new Map()
}
createApp(id, config) {
if (this.apps.has(id)) {
console.warn(`应用 ${id} 已存在`)
return this.apps.get(id)
}
const app = createApp(config)
// 为每个应用添加唯一标识
app.config.globalProperties.$appId = id
app.config.globalProperties.$appManager = this
this.apps.set(id, {
instance: app,
mounted: false,
mountElement: null
})
return app
}
mountApp(id, selector) {
const appData = this.apps.get(id)
if (!appData) {
throw new Error(`应用 ${id} 不存在`)
}
if (appData.mounted) {
console.warn(`应用 ${id} 已挂载`)
return
}
const element = document.querySelector(selector)
if (!element) {
throw new Error(`挂载元素 ${selector} 不存在`)
}
appData.instance.mount(selector)
appData.mounted = true
appData.mountElement = element
console.log(`应用 ${id} 已挂载到 ${selector}`)
}
unmountApp(id) {
const appData = this.apps.get(id)
if (!appData || !appData.mounted) {
console.warn(`应用 ${id} 未挂载`)
return
}
appData.instance.unmount()
appData.mounted = false
appData.mountElement = null
console.log(`应用 ${id} 已卸载`)
}
destroyApp(id) {
this.unmountApp(id)
this.apps.delete(id)
console.log(`应用 ${id} 已销毁`)
}
getApp(id) {
return this.apps.get(id)?.instance
}
getAllApps() {
return Array.from(this.apps.keys())
}
}
// 使用示例
const appManager = new VueAppManager()
// 创建主应用
const mainApp = appManager.createApp('main', {
data() {
return {
title: '主应用',
count: 0
}
},
template: `
<div>
<h2>{{ title }}</h2>
<p>计数: {{ count }}</p>
<button @click="count++">增加</button>
</div>
`
})
// 创建侧边栏应用
const sidebarApp = appManager.createApp('sidebar', {
data() {
return {
title: '侧边栏应用',
items: ['菜单1', '菜单2', '菜单3']
}
},
template: `
<div>
<h3>{{ title }}</h3>
<ul>
<li v-for="item in items" :key="item">{{ item }}</li>
</ul>
</div>
`
})
// 挂载应用
appManager.mountApp('main', '#main-app')
appManager.mountApp('sidebar', '#sidebar-app')// 实例销毁最佳实践
export default {
name: 'ComponentWithCleanup',
setup() {
const timer = ref(null)
const eventListener = ref(null)
const observer = ref(null)
onMounted(() => {
// 设置定时器
timer.value = setInterval(() => {
console.log('定时器执行')
}, 1000)
// 添加事件监听器
eventListener.value = () => {
console.log('窗口大小改变')
}
window.addEventListener('resize', eventListener.value)
// 创建观察器
observer.value = new MutationObserver(() => {
console.log('DOM变化')
})
observer.value.observe(document.body, { childList: true })
})
onBeforeUnmount(() => {
// 清理定时器
if (timer.value) {
clearInterval(timer.value)
timer.value = null
}
// 移除事件监听器
if (eventListener.value) {
window.removeEventListener('resize', eventListener.value)
eventListener.value = null
}
// 断开观察器
if (observer.value) {
observer.value.disconnect()
observer.value = null
}
console.log('组件清理完成')
})
return {
// 组件数据和方法
}
}
}A: 主要区别:1)createApp创建独立的应用实例,避免全局污染;2)更好的TypeScript支持;3)应用级配置替代全局配置;4)支持多个应用实例共存。
A: 可以通过getCurrentInstance()获取当前组件实例,然后通过instance.appContext.app访问应用实例,或使用全局属性。
A: 适用场景:1)微前端架构;2)页面的不同区域需要独立的Vue应用;3)逐步迁移大型应用;4)需要不同配置的独立模块。
A: 使用app.unmount()方法卸载应用,同时清理相关的定时器、事件监听器、观察器等资源,避免内存泄漏。
A: 全局属性在所有组件中都可访问,provide/inject更适合组件树中的数据传递。全局属性适合配置信息,provide/inject适合业务数据。
// 实例调试工具
const debugInstance = (instance) => {
console.group('Vue实例调试信息')
console.log('组件名称:', instance?.type.name)
console.log('实例ID:', instance?.uid)
console.log('父组件:', instance?.parent?.type.name)
console.log('子组件:', Object.keys(instance?.refs || {}))
console.log('应用配置:', instance?.appContext.app.config)
console.groupEnd()
}
// 在组件中使用
export default {
setup() {
const instance = getCurrentInstance()
onMounted(() => {
debugInstance(instance)
})
}
}// 应用状态监控
const monitorApp = (app) => {
const originalMount = app.mount
const originalUnmount = app.unmount
app.mount = function(...args) {
console.log('应用挂载:', args)
const result = originalMount.apply(this, args)
console.log('应用挂载完成')
return result
}
app.unmount = function(...args) {
console.log('应用卸载开始')
const result = originalUnmount.apply(this, args)
console.log('应用卸载完成')
return result
}
return app
}"Vue实例是Vue应用的基础和核心。通过掌握createApp的使用方法、应用配置、多实例管理等技能,你已经具备了构建复杂Vue应用的基础能力。记住,良好的实例管理不仅能提升应用性能,还能让代码更加清晰和可维护。下一步,我们将深入学习Vue实例的属性和方法!"