自定义 HTML 元素在 HTML 树中成功呈现时未呈现在屏幕上

问题描述 投票:0回答:1

我创建了一个自定义 HTML 元素:

class PieChart extends HTMLElement {
    constructor() {
        super();
    } 

    init() {
        this.#render();
    }

    #render() {
        const circleElement = document.createElement("circle");
        circleElement.setAttribute("cx", 100);
        circleElement.setAttribute("cy", 100);
        circleElement.setAttribute("r", 80);
        circleElement.setAttribute("fill", "none");
        circleElement.setAttribute("stroke", "green");
        circleElement.setAttribute("stroke-width", 40);
        circleElement.setAttribute("stroke-dasharray", `502.85 502.85`);

        const svgElement = document.createElement("svg");
        svgElement.style.display = "block";
        svgElement.style.width = "inherit";
        svgElement.style.height = "inherit";
        svgElement.setAttribute("viewBox", `0 0 200 200`);
        svgElement.append(circleElement);

        this.appendChild(svgElement);

        this.style.display  = "block";
        this.style.width = "200px";
        this.style.height = "200px";
    }

    connectedCallback() {
        const event = new CustomEvent("init", {
            bubbles: true
        });
        this.dispatchEvent(event);
    }
}

customElements.define(
    "pie-chart",
    PieChart
);
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" href="./css/site.css" />
</head>
<body>
    <p>Hello!</p>
    <pie-chart></pie-chart>
</body>
</html>
<script>
    document.body.addEventListener("init", (pEvent) => {
        const element = pEvent.target;
        element.init(this);
    });
</script>

此代码执行没有任何问题,并且自定义元素在 DOM 中呈现。但是,圆圈并未呈现在屏幕上。

PS:如果我在浏览器中打开 DOM 并单击 PieChart 元素上的“编辑为 HTML”并更改其中的任何内容并保存,则会出现圆圈。我之前用过几次这个模式,都没有问题,但这次是我第一次使用 SVG 元素。

javascript html custom-element
1个回答
0
投票

这并不是真正创建自定义元素的方式。在connectedCallback中创建一个shadow DOM,浏览器会完成剩下的工作,包括“激活”您注册标签时页面上已经存在的任何自定义元素。

const createSVGElement = tag => document.createElementNS(`http://www.w3.org/2000/svg`, tag);

class PieChart extends HTMLElement {
  constructor() {
    super();
  } 

  connectedCallback() {
    console.log(`let's go`);
    const shadow = this.attachShadow({ mode: "open" });

    const circleElement = createSVGElement("circle");
    circleElement.setAttribute("cx", 100);
    circleElement.setAttribute("cy", 100);
    circleElement.setAttribute("r", 80);
    circleElement.setAttribute("fill", "none");
    circleElement.setAttribute("stroke", "green");
    circleElement.setAttribute("stroke-width", 40);
    circleElement.setAttribute("stroke-dasharray", "502.85 502.85");

    const svgElement = createSVGElement("svg");
    svgElement.setAttribute("viewBox", "0 0 200 200");
    svgElement.append(circleElement);

    shadow.appendChild(svgElement);
      
    const style = document.createElement("style");
    style.textContent = `
      svg {
        display: block;
        width: 200px;
        height: 200px;
      }
    `;
    
    shadow.appendChild(style);
  }
}

customElements.define("pie-chart", PieChart);
<pie-chart></pie-chart>

既然你正在使用 SVG:请记住,即使 SVG 是“HTML 的一部分”,SVG 元素仍然需要在 SVG 命名空间中使用

document.createElemetNS
...这非常奇怪,非常不方便,但我们被困住了有了它。

© www.soinside.com 2019 - 2024. All rights reserved.