我正在尝试使用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/

10-11 23:05
查看更多