课程章节介绍
嗨,同学,咱们今天花几分钟来聊聊 Light DOM 里的事件和插槽,这跟 Shadow DOM 的差别挺大的,你只要抓住“就像普通网页”这个感觉,就很容易理解了。
先说事件。在 Light DOM 里,事件的表现其实跟你熟悉的原生浏览器事件一模一样,因为这里没有 Shadow DOM 那层影子边界来对事件做隔离和重新定位。所以,当你在 Light DOM 里点击某个元素,event.target 永远直接指向真正触发事件的那个元素,不会因为跨了组件边界就被改写。事件也会在所有 Light DOM 的层级里自由自在地向上冒泡,一路传到根节点,没有任何阻挡。
还有一个容易让人困惑的地方:即使你把事件设为 composed: true,它在 Light DOM 下面仍然会冒泡。为什么呢?因为没有影子根来把事件包在里面,composed 这个属性在 Light DOM 里实际上没什么需要破除的边界,事件本身就没有被限制,所以它照样冒泡。
好,说完事件,我们来看看插槽。Light DOM 里的插槽是刻意去模仿浏览器原生影子 DOM 的机制,但注意它是在模仿,很多功能其实没有。最关键的一点是,slot 元素本身在 DOM 树上是不渲染的。你看不到它,它也不会生成任何实际的盒子。这样一来,像 slotchange 事件、::slotted 这种 CSS 伪类选择器,还有插槽附属的生命周期钩子,统统都不能用。那你放进去的内容到哪里去了呢?它们会被直接“展平”到父元素的 DOM 结构里,就好像这些内容是直接写在那儿的一样。
如果你想给插槽命名,机制和原来一样:子元素上放一个 slot 属性,值就是插槽的名字,然后父组件里写一个 name 属性相同的 slot 元素,两边一匹配,内容就分配过去了。但有一件事要特别小心——如果没有匹配到任何命名插槽,也没有放到默认插槽里,那这段内容根本就不会渲染出来,它的生命周期钩子也完全不会触发,等于这段代码就被静默扔掉了。所以开发的时候一定要确认好插槽的匹配,不然可能会莫名其妙地丢失内容。
总结一下:Light DOM 让事件变得透明直接,让你用原生 DOM 的方式去思考;而插槽变得更朴素,丢了 shadow 那一套 API,但依然能靠属性匹配实现内容投影。记住这几个要点,写 Light Web Components 就不会踩坑了。好了,下节课我们再深入实践,下课!
关键词
LWC
Lightning Web Components
Salesforce