在有插槽问题的 Web 组件中使用事件委托(冒泡)
Posted
技术标签:
【中文标题】在有插槽问题的 Web 组件中使用事件委托(冒泡)【英文标题】:Using event delegation (bubbling) in web component with slot problem 【发布时间】:2022-01-16 19:13:12 【问题描述】:我创建了这个简单的示例(纯 JS,不在 Vue 或 React 等中):
<body>
<script>
(function ()
class MyComponent extends htmlElement
constructor()
super();
const shadowRoot = this.attachShadow( mode: 'open' );
const template = document.createElement('template');
template.innerHTML = `
<div>
<button>
<slot> <em>left</em> </slot>
</button>
</div>
`;
shadowRoot.append(template.content.cloneNode(true))
shadowRoot.addEventListener('click', (event) =>
// normal event delegation stuff,
const button = event.target.closest('button');
if (!button) return;
// do somthing with button
console.log(button);
);
customElements.define('my-component', MyComponent);
());
</script>
<my-component id="myComponent"></my-component>
</body>
目前运行良好。
但是,在添加槽之后:
<my-component id="myComponent"> <span>previous</span> </my-component>
事件委托代码坏了,因为我点击的是Light DOM但Shadow DOM,所以,我用const button = event.target.closest('button');
得到了null
有什么建议在槽内使用事件委托?
如果语法有问题,我是中国人:) 感谢您的阅读
【问题讨论】:
请创建一个 MCVE。 ***.com/help/mcve。另请注意,使用插槽时,插槽内容保留在 light DOM 中;它只是为了渲染目的而反映到shadow DOM。这不会改变它在文档中的位置,因此 light DOM 中的任何事件都不会看到 shadow DOM。 @connexo 谢谢,添加了 MCVE。您的评论帮助我确认了我的想法,我认为我必须以另一种方式实现相同的目标。 【参考方案1】:event.composedPath()
输出包含 click
事件传递的所有元素。
跨越所有 shadowRoot 边界。
我把你的代码压缩了一个位...
注意:SO sn-p 控制台速度慢且冗长;检查 TOP OF F12 控制台(所以 sn-p 也可以在那里列出沙盒错误)
<script>
customElements.define('my-component',
class extends HTMLElement
constructor()
super()
.attachShadow(mode:'open')
.innerHTML = `<div>
<button><slot>Left</slot></button>
</div>`;
this.shadowRoot.addEventListener('click', (evt) =>
console.log(evt.composedPath());
);
);
</script>
<my-component></my-component>
<my-component>Right</my-component>
【讨论】:
非常感谢,evt.composedPath() 有效。我只需要在composedPath 数组中找到正确的目标。以上是关于在有插槽问题的 Web 组件中使用事件委托(冒泡)的主要内容,如果未能解决你的问题,请参考以下文章