未渲染的主因是自定义元素shadow DOM中缺失或传入内容非light DOM直接子节点;name属性需字面量精确匹配且大小写敏感;分发异步,须用assignedNodes()或监听slotchange事件检测。

Web Components 的 不是 Vue 或 React 那套响应式插槽,它原生、静态、靠 DOM 树位置和 name 属性匹配,不支持作用域、不触发重新渲染,用错就显示空白。
为什么 什么都没渲染出来
最常见的原因是:自定义元素内部没写 ,或者外部传入的内容没被浏览器识别为“可分发节点”——比如内容在 里、或被 JS 动态 append 进去但没触发 slot 分发(slotchange 事件不会自动重算)。
- 确保自定义元素的 shadow DOM 中至少有一个
,哪怕只是(默认插槽) - 传入内容必须是 light DOM 的直接子节点,例如:
,不能包在标题
正文
里再塞进去- 如果用 JS 动态添加内容,需调用
element.appendChild()后手动触发slot.assignedNodes()检查是否已分发,必要时用requestIdleCallback延迟读取name属性怎么配才生效name是字符串匹配,大小写敏感,且只认属性值字面量,不支持表达式或绑定。一个只会接收 light DOM 中带slot="header"的元素。- 外部节点必须显式写
slot="xxx",例如:欢迎
- 多个同名
slot属性会被合并到同一个命名插槽,顺序按 light DOM 中出现顺序 - 没匹配上的节点会落到默认插槽(无
name的),如果没有默认插槽,那些节点就“消失”——不是隐藏,是根本不会出现在 shadow DOM 中 -
slot属性只能用于 light DOM 直接子节点,嵌套一层就不认了
如何检测插槽内容是否已分发
不能靠
innerHTML或childNodes查 shadow DOM,得用 slot API。分发是异步的,DOM ready 后也不一定立刻完成。- 监听
slotchange事件:shadowRoot.querySelector('slot').addEventListener('slotchange', () => { ... }) - 读取分发结果用
slot.assignedNodes({ flatten: true }),flatten: true能展开命名插槽里的 fallback 内容 - 注意:
assignedNodes()返回的是 live NodeList,但修改它不影响分发结果;想改内容得操作 light DOM 原节点 - 服务端渲染或 SSR 场景下,
不起作用——因为没运行 JS、没 attach shadow DOM,此时 fallback 内容(里的文本)才会显示fallback
最易忽略的一点:slot 分发发生在浏览器 layout 阶段之前,但不保证与 custom element constructor 或
connectedCallback同步。如果你在connectedCallback里立刻调slot.assignedNodes(),大概率拿到空数组——得用Promise.resolve().then()或requestAnimationFrame延后一帧再读。 - 如果用 JS 动态添加内容,需调用










