gpt4 book ai didi

javascript - 创建自定义 HTML 元素的新实例

转载 作者:数据小太阳 更新时间:2023-10-29 06:04:29 24 4
gpt4 key购买 nike

我正在尝试理解新的 HTML 自定义元素。

我的目标是,给定一些数据数组,创建自定义元素的 n 个实例。例如,给定一个包含 10 个用户的列表,创建 10 个用户 html 对象。

好的 - 所以我在 html 中定义了一个自定义元素

HTML

<template-user>
<div class="user-name"></div>
</template-user>

然后我创建我的 Controller

JS

class UserTemplate extends HTMLElement {
constructor(){
super();
this.username = this.querySelectorAll('[class="user-name"]')[0];
}
setName(name){
this.username.innerHtml = name;
}
}
customElements.define('template-user', UserTemplate);

页面加载正常,但现在我对如何重用该元素感到困惑。如果我在做普通的老派东西,我会有一个 for 循环抽出一些 HTML 字符串并设置某些内容的 innerHTML。但现在我宁愿做类似的事情

for(let i = 0; i < users.length; i++){
let userTemplate = new UserTemplate();
userTemplate.setName(user.name);
// append to user list, etc..
}

当我尝试这样做时,它似乎几乎可以工作。但是它找不到username,即this.querySelectorAll 将返回null。只有当我尝试构建该元素的新实例时才会发生这种情况。那么,我应该如何创建新的自定义元素 DOM 对象?

最佳答案

确保您了解 Web 组件构造函数的要求和限制:


https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance

4.13.2 自定义元素构造函数的要求

编写自定义元素构造函数时,作者受以下一致性要求的约束:

  • 对 super() 的无参数调用必须是构造函数主体中的第一条语句,以便在运行任何进一步的代码之前建立正确的原型(prototype)链和此值。
  • return 语句不得出现在构造函数体内的任何位置,除非它是简单的提前返回(return 或 return this)。
  • 构造函数不得使用 document.write() 或 document.open() 方法。
  • 不得检查元素的属性和子元素,因为在非升级情况下不会出现任何属性和子元素,依赖升级会降低元素的可用性。
  • 该元素不得获得任何属性或子元素,因为这违反了使用 createElement 或 createElementNS 方法的消费者的期望。
  • 一般来说,应尽可能将工作推迟到 connectedCallback,尤其是涉及获取资源或渲染的工作。但是,请注意 connectedCallback 可以被多次调用,因此任何真正一次性的初始化工作都需要一个保护来防止它运行两次。
  • 一般来说,构造函数应该用于设置初始状态和默认值,并设置事件监听器和可能的影子根。

在元素创建期间会直接或间接地检查这些要求中的几个,如果不遵守这些要求,将导致自定义元素无法被解析器或 DOM API 实例化。即使工作是在构造函数启动的微任务中完成的,也是如此,因为微任务检查点可以在构造之后立即发生。


您可以进行类似这样的更改:

class TemplateUser extends HTMLElement {
static get observedAttributes() {
return ['user-name'];
}

constructor(){
super();
this.attachShadow({mode:'open'});
this.shadowRoot.innerHTML = '<div></div>';
}

attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal) {
this.shadowRoot.firstChild.innerHTML = newVal;
}
}

get userName() {
return this.getAttribute('user-name');
}

set userName(name) {
this.setAttribute('user-name', name);
}
}

customElements.define('template-user', TemplateUser);


setTimeout( function () {
var el = document.querySelector('[user-name="Mummy"]');
el.userName = "Creature from the Black Lagoon";
}, 2000);
<template-user user-name="Frank N Stein"></template-user>
<template-user user-name="Dracula"></template-user>
<template-user user-name="Mummy"></template-user>

这使用 shadowDOM 来存储 <div> ,然后通过 user-name 设置值属性或通过 userName属性(property)。

关于javascript - 创建自定义 HTML 元素的新实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53036998/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com