Firefox:shadow-DOM 兼容性

Posted

技术标签:

【中文标题】Firefox:shadow-DOM 兼容性【英文标题】:Firefox: shadow-DOM compatibility 【发布时间】:2021-10-08 04:26:27 【问题描述】:

我有一些 javascript 在当前版本的 Chrome 上运行良好,但不适用于 Firefox。 Firefox 的悬停和点击事件触发器失败,我认为这是一个影子 DOM 问题。

我可以用 JavaScript 悬停代码替换 CSS,它适用于 Firefox(不适用于 Chrome),但这不会解决点击事件的问题。

这里如何实现跨浏览器兼容?

let elementsArray = document.querySelectorAll(".icon");
elementsArray.forEach(function(elem) 
    console.log("getting element -"+String(elem));
    elem.addEventListener("mouseenter", function() 
      elem.setAttribute("style", " filter: grayscale(100%);");
    );
    elem.addEventListener("mouseout", function() 
      elem.setAttribute("style", "");
    );
    elem.addEventListener("click", function() 
      let hex = this.getAttribute('id');
      console.log(hex);
    );
);
 <svg 
   
    
   >

<g id="layer0" class="slide" >
<path class="icon" id="y2011_0" d="M 285.0,45.0 300.0,70.98076211353316 285.0,96.96152422706632 255.0,96.96152422706632 240.0,70.98076211353316 255.0,45.0 z" fill="rgba(124,38,10,0.500000)"/>
<path class="icon" id="y2011_1" d="M 330.0,19.019237886466843 345.0,45.0 330.0,70.98076211353316 300.0,70.98076211353316 285.0,45.0 300.0,19.019237886466843 z" fill="rgba(124,39,10,0.500000)"/>
</g>
<use id="use" xlink:href="#layer0" href="#layer0" />
</svg>

【问题讨论】:

可以不给use元素添加事件监听吗? @RobertLongson 这是一个很好的观点,但这会使 g 中的所有路径元素触发事件,而不是单独触发事件 Chrome 不遵守火狐的相同规则。 元素应该创建一个非公开的 DOM。它的影子根设置为“关闭”,在 chrome 中似乎并没有做太多。 “关闭”应该是“拒绝从其外部的 JavaScript 访问已关闭的影子根的节点”(developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow)在 Firefox 中这是真的,document.querySelectorAll(".icon") 行只返回一个长度为 1 的节点列表,而不是包括影子根中的元素。 Chrome 返回 len 2 的列表,包括阴影元素。 【参考方案1】:

如果您动态创建 SVG,则代码更少,控制更多 使用 W3C 标准 Web 组件(所有现代浏览器都支持)

在 FireFox 和 Chromium 中测试的 JSFiddle:https://jsfiddle.net/CustomElementsExamples/qkheyu9a/

<style>
  svg   background: pink 
  path  stroke: blue 
</style>
<game-board>
  <hexagon x="46"  y="0"  />
  <hexagon x="138" y="0"  />
  <hexagon x="92"  y="26" />
  <hexagon x="138" y="52" />
  <hexagon x="92"  y="78" />
  <hexagon x="184" y="26" />
</game-board>
<script>
  customElements.define("game-board", class extends htmlElement 
    connectedCallback() 
      setTimeout(() => 
        let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.innerHTML = `<style>` +
          `.hexagonfill:red.hexagon:hoverfilter:grayscale(100%);cursor:pointer` +
          `.hexclickedfill:green` +
          `</style>`;
        svg.append(...[...this.querySelectorAll("hexagon")].map(hex => 
          let path = document.createElementNS("http://www.w3.org/2000/svg", "path");
          path.setAttribute("d", `m$hex.attributes.x.value $hex.attributes.y.value 15 26-15 26-30 0-15-26 15-26z`);
          path.classList.add("hexagon");
          path.onclick = (evt) => path.classList.toggle("hexclicked");
          return path;
        ));
        this.replaceWith(svg);
      )
    
  )
</script>

&lt;hexagon&gt; 是一个未知元素;保存使用, 见:https://dev.to/dannyengelman/web-components-using-unknownhtmlelements-for-better-semantic-html-5d8c

【讨论】:

以上是关于Firefox:shadow-DOM 兼容性的主要内容,如果未能解决你的问题,请参考以下文章

兼容性将给Firefox附加组件带来的改变

兼容性测试之Firefox浏览器以往版本下载

Firefox 和 Safari 的 css3 flexbox 兼容性问题

firefox兼容性问题

总结IE和Firefox的Javascript兼容性总结

总结IE和Firefox的Javascript兼容性总结