如何在单HTML页面中创建并使用多个独立Vue2应用(结合Django)
多Vue应用独立挂载到Django页面并隔离的解决方案
问题背景
刚接触Vue,正在已完成一半的Django应用中集成Vue + Vuetify + Vuex前端,需要将多个Vue应用独立挂载到HTML页面的不同div中。当前代码可运行,但存在一个应用的模态窗口会在另一个先挂载的应用中打开的问题,且无法采用单入口结合Vue Router的方案,必须由Django提供嵌入Vue组件的HTML页面。
当前配置代码
HTML页面(Django模板)
<div class="tab-content" id="settings-tab-content"> <script type="application/json" id="initial-data"> { "is_superuser": {{ is_superuser|lower }} } </script> <div class="tab-pane fade" id="groups-tab-content" role="tabpanel" aria-labelledby="groups-tab"> <div id="userGroups"></div> </div> <div class="tab-pane fade" id="structure-tab-content" role="tabpanel" aria-labelledby="structure-tab"> <div id="app"></div> </div> </div>
Vue入口JS
import Vue from 'vue' import clinicStructure from './clinicStructure.vue' import userGroups from './userGroups.vue' import router from './router' import store from './store' import vuetify from './plugins/vuetify' import '@mdi/font/css/materialdesignicons.css' import 'vuetify/dist/vuetify.min.css' Vue.config.productionTip = false new Vue({ router, store, vuetify, render: h => h(clinicStructure) }).$mount('#app') new Vue({ router, store, vuetify, render: h => h(userGroups) }).$mount('#userGroups')
package.json构建脚本
{ "build": "vue-cli-service build --dest=../../static/builds/prod", "dev": "vue-cli-service build --dest=../../static/builds/dev --mode=development --watch" }
问题原因
当前代码中,两个Vue实例共用了同一个Vuetify、Router和Store实例,导致Vuetify的全局组件(如模态框)的上下文被绑定到第一个挂载的实例上,进而出现模态窗口串到其他应用的问题。
解决方案
核心思路是让每个Vue应用拥有独立的核心实例(Vuetify、Router、Store),彻底隔离应用间的上下文:
1. 修改Vue入口JS,为每个应用创建独立实例
import Vue from 'vue' import clinicStructure from './clinicStructure.vue' import userGroups from './userGroups.vue' // 导入Router和Store的创建函数而非现成实例 import { createRouter } from './router' import { createStore } from './store' import Vuetify from 'vuetify' import '@mdi/font/css/materialdesignicons.css' import 'vuetify/dist/vuetify.min.css' Vue.config.productionTip = false Vue.use(Vuetify) // 第一个应用:clinicStructure new Vue({ router: createRouter(), // 独立Router实例 store: createStore(), // 独立Store实例(如需共享状态可改为导入同一个store) vuetify: new Vuetify(), // 独立Vuetify实例 render: h => h(clinicStructure) }).$mount('#app') // 第二个应用:userGroups new Vue({ router: createRouter(), // 独立Router实例 store: createStore(), // 独立Store实例 vuetify: new Vuetify(), // 独立Vuetify实例 render: h => h(userGroups) }).$mount('#userGroups')
2. 调整Router和Store的导出方式
确保router/index.js和store/index.js导出的是创建实例的函数,而非直接导出实例:
router/index.js示例
import Vue from 'vue' import VueRouter from 'vue-router' import SomeComponent from '../views/SomeComponent.vue' Vue.use(VueRouter) export function createRouter() { const routes = [ // 该应用的路由配置 { path: '/some-path', component: SomeComponent } ] return new VueRouter({ routes }) }
store/index.js示例
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export function createStore() { return new Vuex.Store({ state: { // 该应用的状态 }, mutations: { // 该应用的mutations }, actions: { // 该应用的actions } }) }
3. 额外注意事项
- 如果需要在多个应用间共享部分状态,可以将这部分状态抽离到独立模块,在
createStore中引入,但每个应用仍需创建独立的Store实例。 - 确保每个Vue应用的根组件没有使用全局事件总线(如
Vue.prototype.$bus),避免应用间的事件干扰。 - Vuetify的全局配置(如主题)可以在
new Vuetify()时统一传入,保证样式一致性的同时保持实例独立。
内容的提问来源于stack exchange,提问作者Iliya
相关产品推荐
相关产品推荐

