如何嵌套Vue应用?主应用挂载后嵌套应用失效及script报错解决方案
问题核心原因
两个异常本质都是Vue主应用的模板编译逻辑导致的:
- Vue挂载到
#vueApp节点时,会遍历该节点下所有DOM做模板解析、重渲染:直接放在节点内部的<script>标签不符合Vue模板的合法标签规则,会直接抛出解析错误;同时重渲染流程会覆盖嵌套应用提前挂载生成的DOM,把嵌套应用绑定的所有事件代理、响应式关联全部冲掉,最终出现DOM外观正常但点击等交互完全无响应的现象。 - 示例代码里的script标签存在基础语法错误:属性名
scr拼写错误,且HTML规范不支持script标签的自闭合写法,这类标签浏览器默认不会执行。
可落地方案
不要把嵌套应用的容器和加载脚本直接放在主Vue的初始模板静态结构里,按以下步骤调整:
第一步:修正基础HTML结构
把嵌套应用的加载逻辑移到主Vue应用挂载逻辑的外层,不要放在#vueApp的静态子节点里,修正script标签的拼写和闭合问题:
<html> <body> <div id="vueApp"> <!-- 此处不要直接放script标签,也不要提前写死嵌套应用的静态容器 --> </div> <!-- 注意属性为src不是scr,script标签必须成对出现,不能用自闭合写法 --> <script src="vueApp.js"></script> </body> </html>
第二步:用v-pre标记嵌套应用挂载容器
在主应用需要嵌入嵌套应用的模板位置,插入带v-pre指令的容器节点——v-pre会告诉Vue编译器完全跳过这个节点和它所有子节点的编译流程,不会重绘内部DOM,从根源上避免冲掉嵌套应用的事件绑定。
主应用模板示例:
<template> <!-- 主应用其他业务模块 --> <div v-pre id="nestedAppMountPoint"></div> <!-- 主应用其他业务模块 --> </template>
第三步:主应用挂载完成后再初始化嵌套应用
在主Vue应用挂载完成的生命周期节点(Vue3为app.mount()执行后,Vue2为实例的mounted钩子),动态加载嵌套应用的JS资源,等资源加载完成后再把嵌套应用挂载到提前标记好的v-pre容器上:
// 以Vue3主应用为例 import { createApp, onMounted } from 'vue' import App from './App.vue' const app = createApp(App) app.mount('#vueApp') onMounted(() => { // 动态创建嵌套应用的脚本标签 const nestedScript = document.createElement('script') nestedScript.type = 'module' nestedScript.src = 'nestedApp.js' // 脚本加载完成后执行嵌套应用挂载逻辑 nestedScript.onload = () => { // 调用嵌套应用暴露的全局初始化方法,挂载到指定容器 window.mountNestedApp('#nestedAppMountPoint') } document.body.appendChild(nestedScript) })
如果主应用是Vue2技术栈,逻辑完全一致,把动态加载、挂载嵌套应用的逻辑放到主Vue实例的mounted生命周期钩子中即可。
注意事项
- 主、嵌套两个Vue应用的实例、状态、响应式上下文完全独立,不要直接跨实例修改内部状态,跨应用通信优先使用
window.postMessage或者全局自定义事件实现 - 嵌套应用的挂载容器必须加
v-pre指令,否则主应用每次触发重渲染到该区域,都会冲掉嵌套应用的DOM和事件绑定 - 禁止将嵌套应用的加载script标签直接写在主Vue挂载节点的静态HTML结构中,这类标签不会被Vue正常执行,还会触发模板解析报错
内容的提问来源于stack exchange,提问作者Gluip
相关产品推荐
相关产品推荐

