templet模板需用<script type="text/html">声明且ID必须存在,禁止动态插入或写在<div>中,否则变量不解析;内联样式和脚本会被剥离,XSS风险须服务端过滤或前端sanitize。

templet模板怎么避免Layui表格的HTML转义失效
Layui表格默认对单元格内容做HTML转义,templet是唯一能绕过这层防护、安全注入结构的出口。但它不是“开了就渲染”,关键在模板定义位置和引用方式。
- 必须用
<script type="text/html">声明模板,不能写在<div>里——否则Layui解析时会把{{=d.xxx}}当普通文本丢进DOM,不执行变量替换 -
templet: '#id'里的#id必须指向已存在的<script>元素,且该元素不能被JS动态插入(如document.body.appendChild()),否则Layui初始化时找不到 - 模板内禁止直接写
<style>或<script>——它们会被剥离,样式需提前定义,交互逻辑得靠lay-event或外部事件委托 - 若数据含
<img src="xss">,{{=d.content}}仍会原样输出,需服务端先过滤或前端用DOMPurify.sanitize()处理后再塞进d.content
服务端模板如何预判组件CSS类名冲突
类名撞车不是运行时才暴露的问题,它在构建阶段就能被识别。关键不是“有没有冲突”,而是“谁在覆盖谁”。
-
class="btn primary"这种写法,在Ant Design和自研UI库共存时,.primary可能被后者重置——但你查不到,因为CSS顺序取决于打包时import顺序,而非HTML里写的先后 - 真正有效的预判方式:用PostCSS插件(如
postcss-prefixwrap)在构建时给整个组件块加前缀,比如把.modal转成[data-app="shop"] .modal,再配合data-app属性手动挂载到容器上 - 别依赖
data-component="button"自动隔离——它只是个标记,没配套构建链路,CSS文件里还是裸写.btn,照样全局生效 - Vue的
<style scoped>和React的Button.module.css必须确认构建配置:Webpack要启用css-loader的modules: { mode: 'local' },否则退化成普通样式
Shadow DOM注入HTML片段时,为什么
直接对shadowRoot.innerHTML赋值含<style>的字符串,等于把样式节点扔进全局文档流——Shadow DOM不会自动拦截或重写它。
- 正确做法是拆解:
DOMParser解析HTML → 提取所有<style>文本 → 用new CSSStyleSheet()创建实例 → 调用shadowRoot.adoptedStyleSheets = [sheet] -
adoptedStyleSheets不支持@import和相对路径(如url(./icon.png)),这些资源必须提前转为绝对URL或预加载到blob:地址 - 如果模板里写了
<script>console.log('hi')</script>,它会在全局上下文执行,不是shadow内部——必须用沙箱(如vm2)重绑定window和document - 延迟调用
this.attachShadow({ mode: 'closed' })会导致污染不可逆:DOM已渲染、样式已计算完毕,再建shadow也晚了
SSR返回的HTML片段怎么安全注入到中
服务端返回的HTML字符串,不是拿来就往<template>里塞的。它必须满足“纯结构”前提,否则会破坏DOM树完整性。
立即学习“前端免费学习笔记(深入)”;
- 片段里严禁出现
<html>、<body>、<head>标签——这些是文档根级容器,<template>只接受<div>、<section>等可嵌套元素 - 用
response.text()拿到字符串后,必须先用DOMParser解析:const doc = new DOMParser().parseFromString(htmlStr, 'text/html'),再取doc.body.children或doc.documentElement.children,避免注释、CDATA干扰 - 若服务端返回的是带
window.__INITIAL_STATE__的完整页面,客户端不能直接template.content.appendChild(...)——hydration边界会断裂,React/Vue状态无法恢复 - 动态插入的区域,必须显式声明hydration边界,比如用
<div id="dynamic-section" data-hydrate="true"></div>,并在客户端调用hydrateRoot()单独处理
postcss-prefixwrap配了但没挂到Vue CLI的vue.config.js里,或者adoptedStyleSheets用了却忘了处理url()路径——这些细节不卡在调试阶段,就卡在上线前半小时。



















