您现在的位置是:网站首页 > <template>-内容模板文章详情
<template>-内容模板
陈川
【
HTML
】
41559人已围观
5376字
<template>
是 HTML5 引入的一个特殊标签,用于声明可重复使用的 HTML 片段。它不会直接渲染到页面上,而是作为 JavaScript 操作的“模板仓库”,通过脚本动态实例化内容。
<template>
的基本特性
<template>
标签内的内容默认具有以下行为:
- 惰性加载:内容不会在页面加载时立即渲染
- 隔离性:模板内的脚本不会执行,图片不会加载
- DOM 访问:需要通过 JavaScript 提取内容
<template id="user-card">
<div class="card">
<h3 class="username"></h3>
<p class="bio"></p>
</div>
</template>
与普通 HTML 的区别
普通 HTML 元素会立即成为 DOM 的一部分,而 <template>
的内容保持“ inert ”状态:
<!-- 这个 div 会立即显示 -->
<div id="visible">立即显示的内容</div>
<!-- 这个 template 需要手动激活 -->
<template id="hidden-template">
<div>不会自动显示的内容</div>
</template>
实际应用场景
动态内容生成
最常见的用法是配合 JavaScript 动态生成重复结构:
const template = document.getElementById('user-card');
const users = [
{ name: '张三', bio: '前端工程师' },
{ name: '李四', bio: 'UI设计师' }
];
users.forEach(user => {
const instance = template.content.cloneNode(true);
instance.querySelector('.username').textContent = user.name;
instance.querySelector('.bio').textContent = user.bio;
document.body.appendChild(instance);
});
配合 Web Components
在自定义元素中使用模板可以提升性能:
class MyElement extends HTMLElement {
constructor() {
super();
const template = document.getElementById('my-element-template');
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(template.content.cloneNode(true));
}
}
customElements.define('my-element', MyElement);
高级用法
嵌套模板
模板可以多层嵌套实现复杂结构:
<template id="page-template">
<header>
<template id="header-content"></template>
</header>
<main>
<template id="main-content"></template>
</main>
</template>
条件模板
结合 JavaScript 实现条件渲染:
function renderTemplate(condition) {
const template = condition
? document.getElementById('template-a')
: document.getElementById('template-b');
return template.content.cloneNode(true);
}
浏览器兼容性处理
虽然现代浏览器都支持 <template>
,但需要兼容旧浏览器时可以这样处理:
if ('content' in document.createElement('template')) {
// 使用模板
} else {
// 降级方案
const div = document.createElement('div');
div.style.display = 'none';
// ...其他降级逻辑
}
性能优化技巧
- 批量操作:在文档片段中完成所有 DOM 操作后再插入
- 预编译:提前克隆模板内容备用
- 缓存查询:避免重复查询模板元素
// 性能优化示例
const cachedTemplate = document.getElementById('my-template').content;
function renderItems(items) {
const fragment = document.createDocumentFragment();
items.forEach(item => {
const instance = cachedTemplate.cloneNode(true);
// ...填充数据
fragment.appendChild(instance);
});
document.getElementById('container').appendChild(fragment);
}
与其他技术的对比
与字符串模板对比
// 字符串拼接方式
function createCard(user) {
return `
<div class="card">
<h3>${user.name}</h3>
<p>${user.bio}</p>
</div>
`;
}
// 模板标签方式
const template = document.getElementById('card-template');
function createCard(user) {
const clone = template.content.cloneNode(true);
clone.querySelector('h3').textContent = user.name;
clone.querySelector('p').textContent = user.bio;
return clone;
}
与 JSX 对比
React 的 JSX 最终也会编译为类似模板的结构:
// JSX
const Card = ({ user }) => (
<div className="card">
<h3>{user.name}</h3>
<p>{user.bio}</p>
</div>
);
// 等效的模板用法
<template id="card-template">
<div class="card">
<h3></h3>
<p></p>
</div>
</template>
实际项目中的最佳实践
- 模板组织:按功能模块拆分模板文件
- 版本控制:模板与 JavaScript 逻辑同步更新
- 文档注释:为模板添加使用说明
<!--
用户卡片模板
使用方式:
1. 克隆模板内容
2. 设置 .username 和 .bio 元素内容
3. 添加到DOM
-->
<template id="user-card">
<!-- 模板内容 -->
</template>
常见问题解决方案
事件绑定问题
模板克隆后需要重新绑定事件:
template.content.querySelector('button').addEventListener('click', handler); // 无效
const clone = template.content.cloneNode(true);
clone.querySelector('button').addEventListener('click', handler); // 有效
样式隔离方案
使用 Shadow DOM 实现样式隔离:
const template = document.getElementById('styled-template');
const host = document.getElementById('host');
const shadow = host.attachShadow({ mode: 'open' });
shadow.appendChild(template.content.cloneNode(true));
模板的扩展用法
服务端渲染配合
在服务端生成模板内容:
// Node.js 环境
const template = `
<template id="server-template">
<div>服务端生成的模板</div>
</template>
`;
res.send(template);
与构建工具集成
Webpack 等工具可以自动处理模板文件:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.html$/,
include: /templates/,
use: 'html-loader'
}
]
}
}
模板的生命周期管理
- 创建阶段:定义模板结构
- 激活阶段:克隆并插入DOM
- 更新阶段:修改已实例化的模板
- 销毁阶段:移除模板实例
// 生命周期管理示例
class TemplateManager {
constructor(templateId) {
this.template = document.getElementById(templateId);
this.instances = new Set();
}
createInstance(data) {
const clone = this.template.content.cloneNode(true);
// ...填充数据
this.instances.add(clone);
return clone;
}
removeInstance(instance) {
instance.parentNode?.removeChild(instance);
this.instances.delete(instance);
}
}
模板的调试技巧
- 在开发者工具中查看
#document-fragment
- 使用
console.dir(template.content)
查看结构 - 添加临时ID辅助调试:
<template id="debug-template">
<div data-debug-id="template-container">
<!-- 内容 -->
</div>
</template>
上一篇: <noscript>-脚本不可用内容
下一篇: <slot>-Web组件插槽