解决 Custom Elements 在 iOS Safari 浏览器中的问题

Custom Elements 是 Web 组件化的重要手段,但是在 iOS Safari 浏览器中存在兼容性问题。本文将介绍其中的问题和相应的解决方案。

兼容性问题

iOS Safari 浏览器中的 Custom Elements 有两个主要问题:

  1. 没有自动触发 constructor:在其他浏览器中,使用 document.createElement() 声明一个 custom element 时,constructor 会自动触发。但在 iOS Safari 中,必须通过 document.body.appendChild(yourElement) 来触发 constructor。
  2. 没有 CSS 自动应用:在其他浏览器中,内置样式会自动应用于 custom element,但在 iOS Safari 中,样式必须通过 JavaScript 显式应用。

这些问题使得 custom element 在 iOS Safari 中无法正常渲染。

解决方案

为了解决上述问题,可以通过 JavaScript 进行相应的操作。

自动触发 constructor

为了在 iOS Safari 中自动触发 constructor,需要监测 custom element 是否被添加到文档中。可以使用 MutationObserver 来监测 DOM 树的变化,并在 custom element 被添加时手动触发 constructor。

示例代码如下:

class MyElement extends HTMLElement {
  constructor() {
    super();
    console.log('constructor');
  }

  connectedCallback() {
    console.log('connectedCallback');
  }
}

if (window.customElements) {
  customElements.define('my-element', MyElement);
} else {
  const observer = new MutationObserver(() => {
    const element = document.querySelector('my-element');
    if (element && !element.connectedCallbackTriggered) {
      element.connectedCallback();
      element.connectedCallbackTriggered = true;
    }
  });
  observer.observe(document.documentElement, { childList: true, subtree: true });
}

自动应用样式

为了在 iOS Safari 中自动应用样式,需要在 custom element 中使用 adoptedStyleSheets 属性。该属性允许 custom element 继承外部样式表,并自动应用到其内部的 Shadow DOM 中。

示例代码如下:

class MyElement extends HTMLElement {
  constructor() {
    super();

    const shadow = this.attachShadow({ mode: 'open' });
    const style = document.createElement('style');
    style.textContent = `
      :host {
        color: red;
      }
    `;
    shadow.adoptedStyleSheets = [style.sheet];
    shadow.innerHTML = 'Hello, world!';
  }
}

customElements.define('my-element', MyElement);

总结

Custom Elements 在 iOS Safari 中存在兼容性问题,但可以通过触发 constructor 和应用样式表来解决。通过上述方案,我们可以更好地在 iOS Safari 上使用 Custom Elements,从而提高 Web 开发效率和用户体验。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b76ce9add4f0e0ffffba05