我创建了一个自定义 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 元素。
这并不是真正创建自定义元素的方式。在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
...这非常奇怪,非常不方便,但我们被困住了有了它。