data-*属性仅存储字符串,不解析html;富文本渲染依赖js动态创建div并innerhtml注入,且必须用dompurify清洗防xss,不可直接赋值。

不能直接用 data- 属性传递富文本内容——它只接受字符串,且浏览器会原样存储、不解析 HTML,更不会执行脚本或渲染样式。
为什么 data-tooltip-html 看似能存富文本,但实际不是“传递”
像 data-tooltip-html="点击保存 <strong>并同步</strong>" 这种写法,只是把一串 HTML 字符串塞进属性里。DOM 解析时不会把它当标签处理,dataset.tooltipHtml 拿到的永远是原始字符串,<strong></strong> 不会被加粗,<script></script> 也不会执行(这是好事)。真正起作用的是后续 JS 手动创建 div 并用 innerHTML 注入——富文本渲染发生在 JS 层,不是 data 属性本身的能力。
- data 属性值始终是字符串,哪怕你写
data-content="<p>hello</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5117" title="HTML Extract"><img src="https://img.php.cn/upload/skill/000/000/081/179033952939354.jpg" alt="HTML Extract" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5117" title="HTML Extract" class="overflowclass">HTML Extract</a> <p class="overflowclass">使用 MinerU 从 HTML 页面和文件中提取内容,将 HTML 转换为保持标题、列表、表格及文本层次结构的干净、结构化 Markdown。F...</p> </div> <a rel="nofollow" href="/xiazai/skill5117" title="HTML Extract" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>",它也只是一个长度为 13 的字符串 - HTML 解析器不会对
data-值做任何 DOM 构建,dataset.content读出来就是"<p>hello</p>",不是节点 - 如果字符串里含未转义的双引号或尖括号,可能破坏 HTML 结构,比如
data-msg='say "hi <b>ok</b>"'就容易出错
dataset 读取富文本字符串后,怎么安全注入到 DOM
拿到字符串后不能直接 el.innerHTML = dataset.tooltipHtml——这会引入 XSS 风险。必须清洗。
- 优先用
DOMPurify.sanitize(dataset.tooltipHtml),白名单控制只留<strong></strong>、<small></small>、<br>等基础标签 - 不用正则替换过滤:它无法处理注释、CDATA、嵌套标签或编码绕过(如
<script>) - 若只支持纯文本+换行,用
textContent+ 手动换行转换:str.replace(/\n/g, '<br>').replace(/ /g, ' ')
- 避免在
constructor()中操作innerHTML,此时子节点尚未挂载,应放在connectedCallback()或事件回调里
替代方案:什么时候该放弃 data-,改用其他方式
当富文本内容较长、含图片、需动态更新或要服务端渲染时,data- 就力不从心了。
- 内容超过 2KB 或含 base64 图片:属性值体积膨胀,影响 HTML 加载和解析,改用
<script type="application/json"></script>块或 API 异步加载 - 需要响应式更新:比如语言切换后 tooltip 内容要变,
data-是静态的,得靠 JS 主动重写属性再重新注入,不如用data-i18n+ 语言包映射 - 服务端预渲染需求:SSR 框架(如 Next.js)中,
data-无法被服务端逻辑识别为结构化数据,应改用 JSON 属性或组件 props - 富文本来自用户输入:绝对不要存进
data-,它没有校验、无生命周期管理,容易成为 XSS 温床
真正难的不是把 HTML 字符串塞进属性,而是决定谁负责解析、谁负责清洗、谁负责挂载——data- 只是起点,不是终点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










