同学们,今天我们来讲一个关于 Light DOM 和 Shadow DOM 样式继承的小知识点,它跟 slot 插槽有关。这个内容如果搞不清楚,可能会让你的组件样式出现意料之外的效果。我们一起来把它拆解开。
首先,想象一个场景:你有一个父组件,在它的模板里使用了一个子组件,并且往子组件的 slot 里放了一些 HTML 元素,比如一段文字或者一个按钮。现在父组件自己定义了一些样式,比如把字体颜色改成红色。那问题来了:这些放在 slot 里的内容,会继承父组件的样式吗?
答案是:会继承,但只继承到这些 slotted 的元素上。也就是说,父组件的样式会“穿透” slot,作用于你塞进去的那个元素的 DOM 上。这在技术上称为“级联”到 slot 里的元素。但是,有一个关键的例外你要记住:作为 slot 容器的那个子组件本身,也就是提供插槽的那个 shadow DOM 组件,它自己是不会收到父组件样式的,除非它主动导入或者用其它方式把这些样式引进来。换句话说,父样式会影响 slot 里的内容元素,却不影响套着 slot 的那个盒子。
这就让样式的作用范围很清楚了:内容样式跟着父组件走,容器组件的内部样式依然是它自己说了算。
现在再讲一个关于 slot 这个 HTML 属性的行为变化。它虽然不起眼,但在版本升级后可能会影响你现有的代码。
在组件模板里,你会给被插入的元素写上 `slot="某个名字"`,这是用来告诉浏览器:“我要去匹配子组件里叫这个名字的插槽”。在过去,API 版本 60.0 及更早的时候,LWC 会在最终渲染出来的 DOM 里保留这个 `slot` 属性。也就是说,你在浏览器检查元素时,能看到 `
` 这样的东西。
但是从 API 版本 61.0 开始,这个 `slot` 属性在 Light DOM 里的 slotted 元素上会被移除,因为它本身只是给 slot 分配算法看的,不影响最终的渲染,所以运行时不再需要保留它。移除的好处是让 DOM 更干净。但要注意,这项清理工作只有一个例外:当你进行 slot 转发的时候,也就是把内容再传给另一个更深层的 shadow slot 时,这个属性必须保留,否则内容就找不到最终的目的地了。
那么,如果你以前的代码或者 CSS 选择器是依赖 `[slot="header"]` 这种属性选择器来工作,升级版本后就可能会失效。官方建议是迁移到使用 `lwc:ref` 指令,或者改用 class、id 等其他选择器,而不要依赖运行时存在的 slot 属性去定位元素。
总结一下今天的内容:父样式能管到 slot 里的内容,但不管提供 slot 的盒子;而 slot 属性在新版本里默认会被删掉,除非你故意转发 slot,否则别用它来做选择器。这样一来,你的组件在样式和属性使用上会更健壮。下次我们聊聊 lwc:ref 的用法,到时你会发现它比 slot 属性要靠谱得多。
好,这节课就到这里,有问题的随时打断我。
关键词
LWC
Lightning Web Components
Salesforce