首页 > 解决方案 > 网页组件组合并不总是在 Chrome 中正确呈现

问题描述

我正在使用在 Firefox 和 safari 中正确呈现但在 chrome 中不正确呈现的 Web 组件组合。确实,有时嵌套组件没有显示在这个浏览器中,我不知道为什么以及如何解决这个问题。

这是代码:

index.html从 json 文件中获取数据并相应地显示 2 个组件。

<html>
<head>
    <meta charset="UTF-8">
    <script type="module" src="/rect-shape.js"></script>
    <script type="module" src="/shape-container.js"></script>
</head>
<body>
    <p>rect-shape:</p>
    <script>
        const innerEl = document.createElement('rect-shape');
        document.body.appendChild(innerEl);
        fetch('./shapes.json')
        .then(response => response.json())
        .then(object => innerEl.color = object.shapes[0].color);
    </script>
    <hr>
    <p>shape-container:</p>
    <script>
        const outerEl = document.createElement('shape-container');
        document.body.appendChild(outerEl);
        fetch('./shapes.json')
        .then(response => response.json())
        .then(object => outerEl.shapes = object.shapes);
    </script>
</body>
</html>

shapes.json:允许参数化来自外部服务的形状

{
    "shapes": [
        {
            "color": "red"
        },
        {
            "color": "blue"
        }
    ]
}

shape-container.js

import '/rect-shape.js';
(function() {
    const template = document.createElement('template');
    template.innerHTML = `
    <style>
        rect-shape {
            display: inline-table;
        }
    </style>
    `;
    class ShapeContainer extends HTMLElement {
        constructor() {
            super();
            this.attachShadow({ mode: 'open' });
            this.shadowRoot.appendChild(template.content.cloneNode(true));
        }
        set shapes(data) {
            try {
                this.shapeArray = data;
                this.renderShapes();
            } catch (error) {
                console.error(error);
            }
        }
        renderShapes() {
            this.shapeArray.forEach(shape => {
                const innerElement = document.createElement('rect-shape');
                this.shadowRoot.appendChild(innerElement);
                innerElement.color = shape.color;
            });
        }
    }
    customElements.define('shape-container', ShapeContainer);
}());

rect-shape.js

(function() {
    const template = document.createElement('template');
    template.innerHTML = `
    <style>
        svg {
            height: 100;
        }
    </style>
    <div>
        <svg id="port-view" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
            <rect width="100%" height="100%" />
        </svg>
    </div>
    `;
    class RectShape extends HTMLElement {
        constructor() {
            super();
            this.attachShadow({ mode: 'open' });
            this.shadowRoot.appendChild(template.content.cloneNode(true));
        }
        set color(value) {
            if (value) {
                this.setAttribute("color", value);
            } else {
            this.removeAttribute("color");
            }
        }
        get color() {
            return this.getAttribute("color");
        }
        static get observedAttributes() {
            return ["color"];
        }
        attributeChangedCallback(name) {
            switch(name) {
                case "color":
                    this.colorizeRect();
                    break;
            }
        }
        colorizeRect() {
           this.shadowRoot.querySelector('rect')
           .style.setProperty('fill', this.color);
        }
    }
    customElements.define('rect-shape', RectShape);
}());

预期渲染: 预期渲染

用 chrome 渲染(有时): 镀铬渲染

我怎么解决这个问题?

谢谢,

标签: javascriptweb-component

解决方案


我清理了代码,保留了您的功能,Chrome 哪里出了问题?

class BaseElement extends HTMLElement {
  constructor() {
    super().attachShadow({mode: 'open'})
           .append(document.getElementById(this.nodeName).content.cloneNode(true));
  }
}
customElements.define('rect-shape', class extends BaseElement {
  static get observedAttributes() {
    return ["color"];
  }
  set color( value ) {
    this.setAttribute("color", value);
  }
  attributeChangedCallback( name, oldValue, newValue ) {
    if (name == "color") this.shadowRoot
                             .querySelector('rect')
                             .style
                             .setProperty('fill', newValue);
  }
});
customElements.define('shape-container', class extends BaseElement {
  set shapes( data ) {
    data.forEach( shape => {
      this.shadowRoot
          .appendChild(document.createElement('rect-shape'))
          .color = shape.color;
    });
  }
});
let shapeArray = {
    "shapes": [{ "color": "red" }, { "color": "yellow" }, { "color": "blue" } ]
  }
$Rect.color = 'rebeccapurple';
$Container.shapes = shapeArray.shapes;
<template id="RECT-SHAPE">
    <style> svg { width: 70px }</style>
    <svg viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
      <rect width="100%" height="100%" />
    </svg>
</template>

<template id="SHAPE-CONTAINER">
  <style> rect-shape { display: inline-table }</style>
</template>

rect-shape:
<br><rect-shape id=$Rect></rect-shape>

<br>shape-container:
<br><shape-container id=$Container></shape-container>


推荐阅读