最安全可控的动态渲染需权衡内容可信性、更新粒度与事件绑定时机:可信数据可用innerHTML,用户输入必须用createElement+textContent;大量节点用DocumentFragment,插入位置敏感时选insertAdjacentHTML;富文本须经DOMPurify过滤。

直接用 innerHTML 或 textContent 赋值是最快的动态渲染方式,但不加约束会引发 XSS 风险、DOM 重排失控和事件丢失——真正安全可控的动态渲染,必须在「内容来源可信性」「更新粒度」和「事件绑定时机」三者间做取舍。
什么时候该用 innerHTML,什么时候该用 createElement
如果数据来自后端 API 且已做过服务端转义(比如 JSON 字段里是纯文本或预 sanitised HTML),innerHTML 可读性高、代码少;但如果数据含用户输入(如评论、昵称、URL),哪怕只拼一个 title 属性,也必须走 createElement + textContent 路线。
-
innerHTML = '—— 危险:用户输' + userInput + ''就执行脚本 -
const el = document.createElement('div'); el.textContent = userInput;—— 安全:自动转义所有特殊字符 - 模板字符串 +
innerHTML看似方便,但只要插值里有任意不可信字段,整条语句就不可信 - 大量节点插入时,
DocumentFragment比反复appendChild更高效,但现代浏览器对小批量操作优化很好,别过早抽象
insertAdjacentHTML 比 innerHTML 多出的关键控制力
innerHTML 是“全量替换”,而 insertAdjacentHTML 允许你把新 HTML 插入到目标元素的指定位置('beforebegin'、'afterbegin'、'beforeend'、'afterend'),不破坏原有子节点结构,也不清空已绑定的事件监听器。
- 给列表末尾追加一项:
list.insertAdjacentHTML('beforeend', '—— 不影响已有- New item
')上的 click handler - 在某个按钮前插入提示:
btn.insertAdjacentHTML('beforebegin', '必填') - 注意:它仍会解析并执行内联脚本(
<script></script>标签),所以依然不能用于不可信内容 - 相比先
cloneNode再appendChild,它更轻量,适合一次性注入静态结构片段
模板字符串 + document.createElement 的最小安全组合
想兼顾可读性与安全性?用模板字符串生成结构骨架,再用 createElement 和 setAttribute 填充动态部分,最后用 append 或 prepend 插入 DOM。
- 错误写法:
el.innerHTML = `——${title}`title未转义 - 正确写法:
const card = document.createElement('div'); card.className = 'card'; card.dataset.id = id; card.textContent = title; container.append(card); - 若需插入带标签的富文本(如后台返回的 Markdown 渲染结果),必须用 DOMPurify 或内置
DOMParser过滤后再innerHTML,不能跳过这步 - 避免在循环中反复调用
querySelector查找容器,提前缓存引用
最容易被忽略的是事件委托的绑定时机:动态插入的按钮,如果用 element.addEventListener 直接绑定,必须在插入 DOM 后立即执行;更稳妥的做法是把事件监听写在父容器上,用 event.target.matches('.btn-delete') 判断触发源——这样连后续插入的节点都自动生效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











