如何为Vue.js实例动态应用创建的模板?解决动态渲染失效问题
嘿,这个问题我之前也碰到过!核心原因其实很简单——Vue在初始化实例的时候,只会编译挂载时已经存在于DOM里的模板内容。你动态创建的dynamicTemplate是在Vue初始化完成后才塞到页面里的,Vue根本没察觉到这部分新内容,自然不会去编译它,所以secondPlaceholder就没被正确渲染出来。
接下来给你几个靠谱的解决方案,按需选就行:
方案一:手动编译+挂载动态模板(最直接)
直接用Vue的Vue.compile把动态模板编译成渲染函数,然后创建一个子Vue实例挂载到目标容器上,这样就能让Vue处理动态模板里的插值了:
<!doctype html> <html> <head> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> </head> <body> <div id="app"> <div id="firstPlaceholder"></div> <div id="secondPlaceholder"></div> </div> <script type="text/x-template" id="staticTemplate"> <div>{{ text }}</div> </script> <script> const app = new Vue({ el: '#app', data: { text: 'Hello Vue!' }, mounted() { // 静态模板正常渲染 this.$mount('#firstPlaceholder'); // 处理动态模板 const dynamicTemplate = `<div>{{ text }}</div>`; // 编译动态模板得到渲染函数 const compiledTemplate = Vue.compile(dynamicTemplate); // 创建子实例并挂载到secondPlaceholder new Vue({ render: compiledTemplate.render, staticRenderFns: compiledTemplate.staticRenderFns, // 可以直接复用父组件的data,或者自己定义 data: () => ({ text: this.text }) }).$mount('#secondPlaceholder'); } }); </script> </body> </html>
方案二:用动态组件渲染(更符合Vue风格)
如果你的动态模板需要复用,或者想更贴合Vue的组件化思想,可以把动态模板封装成一个组件,然后通过<component>标签动态渲染:
<!doctype html> <html> <head> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> </head> <body> <div id="app"> <div id="firstPlaceholder"></div> <!-- 用动态组件渲染 --> <component :is="dynamicComp"></component> </div> <script type="text/x-template" id="staticTemplate"> <div>{{ text }}</div> </script> <script> const app = new Vue({ el: '#app', data: { text: 'Hello Vue!', dynamicComp: null }, mounted() { // 静态模板渲染 this.$mount('#firstPlaceholder'); // 动态注册组件 this.dynamicComp = Vue.component('dynamic-template', { template: `<div>{{ text }}</div>`, data: () => ({ text: this.text }) }); } }); </script> </body> </html>
补充:Vue 3的适配
如果是用Vue 3,API稍微有点变化,Vue.compile变成了直接导入compile方法,挂载方式也更简洁,核心思路还是一样的——手动让Vue编译动态模板内容,比如:
import { createApp, compile } from 'vue' const app = createApp({ data() { return { text: 'Hello Vue 3!' } }, mounted() { const dynamicTemplate = `<div>{{ text }}</div>` const { render } = compile(dynamicTemplate) // 创建子应用挂载到目标元素 createApp({ render, data: () => ({ text: this.text }) }).mount('#secondPlaceholder') } }).mount('#app')
最后提醒一句:如果动态模板的内容是用户输入的,一定要做好XSS防护,别让恶意代码钻空子哦!
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

