核心是插入时机与方式:innerHTML会清空节点、丢失事件和状态;insertAdjacentHTML安全追加但script不执行;DocumentFragment批量插入防重排;customElements.define()封装才实现真模块化。

动态内容中插入自定义模块,核心不是“能不能插”,而是“用什么时机、什么方式、插完会不会丢事件或样式”。纯靠 innerHTML = '...' 最快,但也是最危险的——它会清空原有子节点、销毁已绑定的事件监听器、重置 <input> 的值,且无法执行新插入的 <script></script> 标签。
用 insertAdjacentHTML() 安全追加 HTML 字符串
这是最常用也最可控的 DOM 插入方式。它不破坏现有结构,支持四种插入位置,且能一次性写入多节点(比反复 appendChild() 更轻量)。
-
beforebegin:插入到目标元素外部、之前(同级) -
afterbegin:插入到目标元素内部、开头(第一个子节点前) -
beforeend:插入到目标元素内部、末尾(等效于appendChild()) -
afterend:插入到目标元素外部、之后(同级)
例如向 <div id="module-container"></div> 末尾插入一个自定义模块:
const container = document.getElementById('module-container');
container.insertAdjacentHTML('beforeend', `<div class="custom-module"><h3>公告</h3><p>系统维护中</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p></div>`);
注意:插入的 HTML 中若含 <script></script>,仍不会自动执行;需手动提取并 eval() 或 document.createElement('script') 注入。
用 DocumentFragment 批量插入避免重排
当你要一次插入 10+ 个模块(比如从 API 拉回的列表),直接循环调用 insertAdjacentHTML() 会触发多次 DOM 重排,卡顿明显。此时应先构造 DocumentFragment,再一次性挂载。
- 创建
const frag = document.createDocumentFragment() - 循环创建模块节点(
document.createElement()+ 设置innerHTML或属性) - 每个节点都
frag.appendChild(node) - 最后只调用一次
container.appendChild(frag)
这样浏览器只做一次布局计算,性能提升显著。尤其适合后台管理页、仪表盘等模块密集型场景。
自定义元素(Custom Element)才是真·模块化
如果“自定义模块”需要复用、带状态、响应属性变化,硬塞 HTML 字符串就太原始了。应该用原生 customElements.define() 封装。
-
constructor()里只做基础初始化(super()、this.attachShadow({ mode: 'open' })),**不能操作 DOM** - 所有 DOM 渲染、事件绑定、数据请求必须放在
connectedCallback()里 - 想让
<my-notice title="警告"></my-notice>响应title变更?得配合static get observedAttributes()和attributeChangedCallback() - Shadow DOM 中样式不会自动加载 CSS 文件,必须用
CSSStyleSheet+adoptedStyleSheets显式注入,漏掉这步,样式就失效
比如一个可配置的提示模块:<alert-banner type="error" message="网络异常"></alert-banner>,它的行为和样式完全封装在类定义里,插入时只需写标签,不用管怎么渲染——这才是模块化的实质。
真正容易被忽略的点是:动态插入后,你是否还持有对这些模块的引用?是否要监听它们的生命周期?是否要清理它们绑定的定时器或 fetch 中断?这些不在插入动作本身,却决定模块能否长期稳定运行。



















