使用 cloneNode 克隆模板
使用 cloneNode(true) 高效生成模板内容
使用 cloneNode 克隆模板 是 CoddyKit 上的免费 HTML Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 HTML Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 HTML Academy 课程共包含 4 节课。
深层克隆与浅层克隆
cloneNode 方法接受一个布尔参数:
const template = document.getElementById('card-tmpl');
// Deep clone (true): copies all descendants
const deep = template.content.cloneNode(true);
// Shallow clone (false): only the root node, no children
const shallow = template.content.cloneNode(false);
// shallow has no children — use deep for templates从一个 template 创建多个副本
template 可以被克隆任意次数:
const tmpl = document.getElementById('item-tmpl');
const container = document.getElementById('list');
['Alpha', 'Beta', 'Gamma'].forEach((name, i) => {
const clone = tmpl.content.cloneNode(true);
clone.querySelector('.item-name').textContent = name;
clone.querySelector('.item-num').textContent = i + 1;
container.appendChild(clone);
});
// 3 separate clones — modifying one doesn't affect othersDocumentFragment 与性能
使用 DocumentFragment 批量更新 DOM,以提升性能:
const frag = document.createDocumentFragment();
const tmpl = document.getElementById('row-tmpl');
rows.forEach(row => {
const clone = tmpl.content.cloneNode(true);
// fill in clone...
frag.appendChild(clone);
});
// ONE DOM append instead of many:
document.getElementById('table-body').appendChild(frag);
// Appending to a fragment doesn't trigger layout; append once for performance克隆与事件监听器
原始 template 上的事件监听器不会被复制:
// Template definition:
const tmpl = document.getElementById('btn-tmpl');
const origBtn = tmpl.content.querySelector('.btn');
origBtn.addEventListener('click', () => console.log('click'));
// Clone:
const clone = tmpl.content.cloneNode(true);
const cloneBtn = clone.querySelector('.btn');
// cloneBtn does NOT have the click listener!
// You must re-add listeners after cloning克隆后添加监听器
在克隆后附加事件:
function createCard(data) {
const clone = document.getElementById('card-tmpl').content.cloneNode(true);
const deleteBtn = clone.querySelector('.delete-btn');
deleteBtn.addEventListener('click', () => deleteItem(data.id));
clone.querySelector('.title').textContent = data.title;
return clone; // return the fragment
}
document.getElementById('list').appendChild(createCard(item));使用 importNode
document.importNode 是 cloneNode 的替代方案:
const tmpl = document.getElementById('card-tmpl');
// Equivalent to tmpl.content.cloneNode(true):
const clone = document.importNode(tmpl.content, true);
// importNode adopts the node into the current document
// In the same document, this is functionally identical to cloneNodetemplate 插槽预览
Web Components 使用命名插槽将内容注入 template:
<template id="card-tmpl">
<div class="card">
<slot name="title">Default Title</slot>
<slot name="body">Default body text.</slot>
</div>
</template>
<!-- slot elements become placeholders for projected content -->
<!-- Covered in full in the Shadow DOM course -->更新克隆的内容
填充克隆 template 内容的方法:
const clone = tmpl.content.cloneNode(true);
// textContent — safe, no HTML parsing:
clone.querySelector('.name').textContent = user.name;
// innerHTML — only if content is trusted:
clone.querySelector('.bio').innerHTML = trustedHTML;
// setAttribute:
clone.querySelector('.avatar').src = user.avatar;
clone.querySelector('.profile-link').href = `/users/${user.id}`;与 document.createElement 比较
对于重复项目,比较 template 与 createElement:
// createElement: verbose for complex structures
const card = document.createElement('div');
card.className = 'card';
const title = document.createElement('h2');
card.appendChild(title);
// ... many lines for nested structure
// template: define once, clone efficiently
const clone = tmpl.content.cloneNode(true);
// Complex structure defined in HTML once
// Clone is fast and the template handles nesting内存与 template
template 的内存行为:
- template 以 DocumentFragment 的形式存储在内存中
- 克隆是相互独立的副本——从 DOM 中移除后会由垃圾回收机制回收
- 只要 DOM 元素存在,template 本身就会持续存在
- 对于动态 template,请将 template 引用缓存在函数外部
浏览器支持
template 元素支持情况:
- 自约 2014 年起,所有现代浏览器都支持
- IE 不支持(IE 已停止生命周期)
- 现代项目不需要 polyfill
快速检查
为什么克隆 template 后必须重新添加事件监听器?
回顾:cloneNode
cloneNode 的核心要点:
cloneNode(true)——包含所有后代节点的深层副本- 事件监听器不会被复制——克隆后需要重新附加
- 使用 DocumentFragment 批量追加以提升性能
- 在渲染循环外缓存 template 引用
- 使用 textContent 安全地插入文本
常见问题解答
「使用 cloneNode 克隆模板」课时是免费的吗?
是的 — 「使用 cloneNode 克隆模板」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 HTML Academy 课程的其余内容,请升级到 CoddyKit PRO。 HTML Academy 课程共包含 4 节课。
「使用 cloneNode 克隆模板」这节课中我会学到什么?
使用 cloneNode(true) 高效生成模板内容 你通过在浏览器中直接运行的动手代码来练习 HTML Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 HTML Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 HTML Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 cloneNode 克隆模板」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 HTML Academy 课中编写并运行代码吗?
能。每节 HTML Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- template 元素:惰性内容
- 使用 cloneNode 克隆模板
- 将 template 用于 JavaScript 渲染
- 模板与 innerHTML 的安全性