标签本身不实现复用,必须手动克隆(clonenode(true))、填充数据、插入dom;仅在自定义元素的shadow dom中生效;构建时预处理比运行时js更可靠;语义标签是结构复用的前提。

直接用 <template></template> 不等于实现了复用
很多人把 <template id="card"></template> 往页面里一放,就以为组件化完成了。其实不然:<template></template> 只是浏览器跳过的 DOM 容器,它不支持传参、不支持条件渲染、不自动更新。你必须手动调用 template.content.cloneNode(true),再逐个填充 textContent 或 src,最后 appendChild 到目标节点。漏掉 cloneNode(true),直接 appendChild(template),页面什么也不会显示;用 innerHTML 去塞数据,又可能引入 XSS 风险。
<slot></slot> 必须配合 Custom Element 才生效
<slot></slot> 在独立 HTML 文件或普通 JS 脚本里是“哑巴”——它只在自定义元素的 Shadow DOM 中起作用。比如你写了个 <user-card></user-card>,里面用了 <slot name="avatar"></slot>,那只有在 class UserCard extends HTMLElement 的 connectedCallback 里调用 this.attachShadow 并 appendChild(template.content.cloneNode(true)),<slot></slot> 才会把外部传入的内容正确分发进去。单独把 <slot></slot> 放在普通页面里,它只会原样输出为文字节点。
构建时预处理比运行时 JS 更可靠
如果你的项目是静态站点(文档页、营销页),优先选构建时方案,比如 posthtml-include 或 html-webpack-plugin 的 preprocessor。它们在打包阶段就把 <include src="header.html"></include> 替换成真实 HTML,最终输出的是纯静态结构,SEO 友好、首屏快、无 JS 依赖。而运行时用 fetch() 加载片段,会触发额外请求、延迟渲染、破坏服务端可索引性;且一旦网络失败或 JS 报错,整个区域就空白。
语义标签不是装饰,而是复用的前提
没有 <header></header>、<nav></nav>、<article></article> 这类语义边界,模板就只是“一堆 div 的集合”。当你把导航抽成 nav.html,靠的是 <nav></nav> 标签本身声明了“这是一个导航区块”,而不是靠 class 名叫 top-nav 或 main-menu。JS 脚本可以统一监听 document.querySelector('nav'),CSS 可以写 nav ul { … },框架也能据此自动注入无障碍属性。否则,复用的只是样式壳子,不是结构逻辑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











