我正在尝试使用Shadow DOM封装自定义事件冒泡,但仍然从外部获取样式。
我尝试使用slot并发现保留了外部样式,但是无法封装事件。
我试图直接将child附加到shadowroot,但是后来我失去了所有外部样式。
所以我想要实现的是...
外部样式可以渗入,在这种情况下跨度将变为颜色:红色
自定义事件'span-clicked'被组件的边界阻止
标准事件(例如click)将整个组件视为srcElement
有没有办法可以实现上述三个目标?非常感谢你!
var outer = document.getElementById('outer');
var shadowroot = outer.attachShadow({mode: 'open'});
shadowroot.innerHTML = `
<slot></slot>
`;
var spanInsideShadow = document.getElementById('span_inside_shadow');
shadowroot.appendChild(spanInsideShadow);
var spanInLightDom = document.getElementById('span_in_slot');
spanInsideShadow.addEventListener('click', function(e){
spanInsideShadow.dispatchEvent(new Event('span-clicked', {bubbles: true}));
});
outer.addEventListener('span-clicked', function(e){
console.log('outer received custom event. Do not want this!');
});
outer.addEventListener('click', function(e){
console.log('click event received, source elem = ', e.srcElement);
});
span {
color: red;
}
<div id='outer'>
<div id='inner'>
<span id='span_light_dom'> SPAN_IN_LIGHT_DOM_BUT_RENDERED_IN_SLOT </span>
</div>
</div>
<div>
<span id='span_normal'>A_NORMAL_SPAN_OUTSIDE </span>
</div>
<div>
<span id='span_inside_shadow'>SPAN_WILL_BE_APPENDED_TO_SHAODOW_ROOT</span>
</div>
我希望我能解释得足够清楚。非常感谢您的帮助!
最佳答案
自动转换事件目标并将外部样式转换为Shadow DOM的唯一方法是将所有DOM和CSS包括在Shadow DOM中。而不是使用<slot>
。
如果要通过<link>
标记加载外部CSS文件,则可以在影子DOM中包含相同的<link>
标记。
如果要在主页中包含<style>
标记,则需要在影子DOM中包含该clone
标记的<style>
。
在我撰写本文时,您唯一的其他选择是使用CSS变量,该变量将允许外界更改内部CSS的值。但是随后您必须编写CSS才能使用变量。
无论选择哪种方式,如果您将这些样式复制到CSS变量中或通过CSS变量来影响它们,则都只会影响Shadow DOM中元素的样式。如果您不包括一些新的,意外的CSS,那么它将不会被应用。
并且由于您希望Shadow DOM转换事件的目标,因此必须将DOM放置在阴影中,而不要使用<slot>
。
还有其他方法正在研究中,但是这些方法将在一段时间内消失。大概几年了。
我希望这回答了你的问题。不幸的是,我认为这不是您要查找的。
关于javascript - 如果我想从外部保留事件,但如何防止自定义事件冒泡,如何隐藏DOM,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46495782/