是原生 HTML 惊惰性容器,不参与 Vue 编译与响应式系统,故不支持 v-model 或 {{ }};其内容需手动克隆并交由 Vue 动态挂载才能启用数据绑定。

<template></template> 标签本身不参与数据绑定,也不支持双向绑定——它只是个惰性容器,内容不会被渲染、不执行脚本、不触发网络请求,更不会自动响应数据变化。
为什么 <template></template> 不能直接用 v-model 或 {{ }}
Vue、React 等框架的模板语法(如 v-model、{{ }}、{message})只在组件模板编译阶段起作用,而 <template></template> 是原生 HTML 元素,浏览器解析时直接跳过其内容,框架根本“看不到”里面写了什么。你写 <template><input v-model="msg"></template>,Vue 不会解析这行,也不会注册响应式依赖。
常见错误现象:
- 在
<template></template>内写v-model,控制台无报错但完全没反应 - 用
document.querySelector('template').content取出节点后直接插入 DOM,发现绑定丢失、事件不触发 - 以为
<template></template>是“可复用的 Vue 模板片段”,结果发现 props、data、生命周期全失效
怎么让 <template></template> 和框架协同工作
核心思路:把 <template></template> 当作纯结构载体,用 JavaScript 克隆 + 手动挂载到框架可控范围内,再由框架接管后续响应式逻辑。
立即学习“前端免费学习笔记(深入)”;
以 Vue 3 为例,典型做法是:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 把
<template id="item-tpl"><li>{{ label }}</li></template>放在 HTML 中(仅作结构声明) - 在组件内用
ref()或querySelector获取该模板的content - 用
createApp()或defineComponent()动态创建一个微型组件,把克隆的节点作为render函数返回值 - 或更实际的做法:用
<slot></slot>+template#xxx语法替代硬编码的<template></template>标签
简短示例(Vue 3 setup):
<template id="dynamic-item">
<li class="item"><span>{{ text }}</span><button @click="remove">×</button></li>
</template>
<p><script setup>
import { ref, onMounted } from 'vue'
const list = ref([{ id: 1, text: 'task 1' }])
const template = document.getElementById('dynamic-item')</p><p>onMounted(() => {
// 注意:这里只是克隆结构,不带响应式!
const fragment = document.importNode(template.content, true)
// 真正要绑定数据,还得靠 Vue 的 render 或 createApp
})
</script>微信小程序和 Blazor 的特殊处理
微信小程序的 <template></template> 是框架级语法糖,和 HTML 原生 <template></template> 同名但不同物——它的 name 属性配合 <import></import> 和 <include></include> 才能复用,且支持 {{ }} 插值;但它依然不是双向绑定的源头,input 的 bindinput 仍需手动调用 this.setData()。
Blazor 中的 <template></template>(如 RenderFragment)本质是 C# 委托,能捕获闭包变量,所以看起来像“自动绑定”,实则是编译期生成的委托调用链,与 HTML <template></template> 无任何关系。
关键区别:
- 原生
<template></template>:DOM 层存在,但不可见、不激活、无上下文 - Vue/React 的模板语法:编译期产物,运行时由虚拟 DOM 驱动
- 小程序/Blazor 的
<template></template>:框架自定义解析器识别的指令,非标准 HTML 行为
真正容易被忽略的一点:当你在项目里混用原生 <template></template> 和框架模板时,调试工具(如 Vue Devtools)完全感知不到前者——它既不显示在组件树里,也无法查看其内部响应式状态。这意味着所有基于它的动态逻辑,必须显式桥接,不能依赖框架自动推导。


















