html本身不支持组件拆分,必须靠javascript驱动;template和slot仅为声明性容器,需js调用clonenode、attachshadow等api才能实例化、挂载并实现内容分发与作用域隔离。

HTML 本身不支持组件拆分,必须靠 JS 驱动
纯 HTML 没有“组件”概念,<template></template>、<slot></slot> 或自定义元素(Custom Elements)只是容器或占位符,不自动渲染、不管理生命周期、不隔离作用域。所谓“HTML 实现组件拆分”,本质是用 HTML 做结构声明,靠 JavaScript 控制加载、实例化和挂载。
常见误区是把多个 <div class="component-home"> 写死在 index.<a style="color:#f60; text-decoration:underline;" title="html" href="https://m.php.cn/zt/15763.html" target="_blank">html</a> 里再 show/hide——这不算拆分,只是 DOM 切换,代码仍耦合、无法复用、不可按需加载。
<ul>
<li>
<code><template id="home"></template> 只是内存中的文档片段,需 JS 调用 content.cloneNode(true) 才能插入 DOM
<script type="module"></script> 加载组件 JS 文件时,路径必须是相对或绝对 URL,不能写 ./home.js 后直接执行——浏览器会报 CORS 或 MIME 类型错误import() 动态导入,返回的是 Promise,必须 await 或 .then(),否则 innerHTML 会塞进去个 [object Module]用 + JS 实现最小可行组件拆分
这是最轻量、无框架的落地方式,适合静态内容为主、路由简单的小型 SPA。
关键不是写多少 HTML,而是怎么组织加载时机和作用域:
- 每个组件对应一个
<template id="xxx"></template>,内部可含内联样式(<style scoped></style>不生效,得靠类名前缀或 CSS 自定义属性隔离) - 组件 JS 文件导出一个函数,如
renderHome(container),接收目标 DOM 节点,负责克隆模板、绑定事件、初始化状态 - 路由切换时,清空
main内容,再调用对应 render 函数,例如:renderAbout(document.querySelector('main')) - 避免反复
innerHTML = ...,改用replaceChildren()或textContent = ''+appendChild(),防止事件监听器丢失
为什么不能只靠 或
<link rel="import"> 已被 Chrome 废弃(2019 年起),Firefox 从未支持;<iframe></iframe> 隔离太强:父页面无法直接访问子页面 DOM,通信需 postMessage,样式/脚本不共享,滚动、焦点、SEO 全部断裂。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
真实项目中踩过的坑:
- 用
<iframe src="about.html"></iframe>当组件,结果点击链接跳转整个 iframe,而非主页面 URL ——history.pushState对 iframe 无效 - 试图用
document.write()向 iframe 写入 HTML,但 iframe 加载完成前写入会清空其文档,且跨域时直接报错 - 依赖
shadowRoot做样式封装,但手动 attach shadow DOM 后,querySelector默认查不到影子节点内的元素,必须显式调用shadowRoot.querySelector
语义化标签如何配合组件拆分
<main></main> 是组件挂载的唯一合法父容器,所有路由视图必须严格包裹其中;<header></header> 和 <nav></nav> 属于壳层(shell),不应随路由销毁重建;而 <article></article>、<section></section> 才是组件级语义单位。
容易忽略的细节:
- 每次切换组件后,要重设
document.title,否则浏览器历史记录里全是初始标题 - 用
<aside></aside>放侧边栏时,确保它在<main></main>外——否则屏幕阅读器会把它当成当前页面内容的一部分 - 加载中状态应放在
<main></main>内部,用<div aria-busy="true"> 而非全局遮罩,保证无障碍焦点流连续 <li>服务端返回的 index.html 必须包含完整壳层(<code><header></header>、<nav></nav>、<main></main>),否则 SSR 或直出时结构断裂
真实项目里,组件拆分最难的从来不是怎么写 HTML,而是状态边界在哪、事件怎么委托、错误如何降级、滚动位置怎么保持——这些全靠 JS 精细控制,HTML 只提供骨架。










