slot标签必须配合attachShadow才生效,需满足三条件:调用attachShadow、shadowRoot含slot、自定义元素已注册升级;直系子节点才匹配,具名插槽严格字符串匹配,可用assignedNodes()验证分发。
写了 <slot></slot> 却没渲染出内容?不是代码写错了,是机制根本没启动。浏览器原生的 slot 是 Shadow DOM 的投影机制,普通 DOM 里放 <slot> 完全无效,会被当成无意义标签忽略。
必须满足三个条件才能让 slot 工作:
this.attachShadow({ mode: 'open' })
shadowRoot 内部 HTML 确实包含对应 <slot name="xxx"></slot>
customElements.define() 注册并完成升级(即 DOM 中的标签已“活”过来)常见错误:在普通 <div><slot></slot></div> 里尝试使用 —— 这种写法永远不生效。
slot 匹配只看“直接子节点”,中间插一层包裹元素就会静默失效。这是最容易踩的坑,且不会报错、不会警告。
立即学习“前端免费学习笔记(深入)”;
比如这个能命中:<my-card><h2 slot="title">Hello</h2></my-card>;但这个完全无效:<my-card><div><h2 slot="title">Hello</h2></div></my-card> —— 因为 <div> 是直系子节点,<h2> 是它的后代,slot 不会穿透。
这意味着:组件使用者必须按约定结构传入内容,组件作者无法靠 CSS 或 JS “修复”这种嵌套。
<slot name="footer"></slot> 只接收 slot="footer" 的节点,大小写、空格、引号类型(单/双)都必须完全一致。
常见陷阱:
slot=" Footer "(首尾空格)→ 不匹配slot='footer'(单引号)→ 可以,HTML 属性值引号不影响解析slot="footer-2" vs <slot name="footer"></slot> → 不匹配查证是否成功分发,可以用 slot.assignedNodes() 检查返回的 NodeList,空数组说明没匹配上。
如果模板用的是 {{name}} 这类占位语法,想提取所有变量名,别用 String.prototype.match() —— 它只返回第一个匹配项。
推荐写法:
for (const match of htmlTemplate.matchAll(/{{(w+)}}/g)) { console.log(match[1]); // 输出 'name', 'user', 'avatar' 等}
注意点:
g 标志,否则 matchAll 报错{{user.profile.name}}),正则要改成 /{{([w.]+)}}/g
真正难的不是写正则,而是确认模板格式统一、且没有嵌套干扰 —— 实际项目里,混合了 {{}} 和 ${} 的模板常导致漏提取。