【问题标题】:Cannot access attributes of a custom element from its constructor无法从其构造函数访问自定义元素的属性
【发布时间】:2017-07-04 05:09:47
【问题描述】:

我正在尝试使用自定义元素 API 为游戏内浏览器引擎使用的自定义元素创建各种 polyfill,以显示按钮和类似内容。 但是,我似乎无法从构造函数中访问元素的属性(例如 src、href ...)。

这是一个例子:

class KWButton extends HTMLElement {
  constructor() {
    super();
    var attributes = this.attributes;
    var shadow = this.attachShadow({
      mode: 'open'
    });
    var img = document.createElement('img');
    img.alt = this.getAttribute('text'); // the getAttribute call returns null
    img.src = this.getAttribute('src'); // as does this one
    img.width = this.getAttribute('width'); // and this
    img.height = this.getAttribute('height'); // and this
    img.className = 'vivacity-kwbutton'; // this works fine
    shadow.appendChild(img);
    img.addEventListener('click', () => {
      window.location = this.getAttribute('href'); // this works perfectly fine
    });
  }
}
customElements.define('kw-button',
  KWButton);
<kw-button src="https://placekitten.com/g/198/39" width="198" height="39" icon_src="https://placekitten.com/g/34/32" icon_width="34" icon_height="32" href="https://placekitten.com/" text="placekiten" color="#ffffff" size="18"></kw-button>

【问题讨论】:

  • 据我所知,这似乎工作正常。请注意,延迟 connectedCallback 生命周期事件的工作(例如创建和加载图像)可能是明智的。
  • @lonesomeday 这很奇怪;它似乎没有在我的页面上运行 (vivacity.fs3d.net)

标签: javascript html custom-element


【解决方案1】:

您无法使用querySelector()appendChild() 访问元素DOM 树,以及constructor() 中的getAttribute()setAttribute() 属性。

这是因为在调用constructor() 时,自定义元素还没有内容。

你应该在 connectedCallback() 方法中推迟它,它会没事的。

来自the specs

元素不得获得任何属性或子元素,因为这违背了使用 createElement 或 createElementNS 方法的消费者的期望。

一般来说,工作应该尽可能的推迟到connectedCallback

【讨论】:

  • 感谢您引用规格!但是,“这是因为在调用 constructor() 时自定义元素还没有内容”部分对我来说有点误导:在谈论 DOM 元素时,“内容”通常表示 HTML 内容。 (而这里的问题是,AFAIK,对象的 DOM 相关状态没有初始化,因为它还没有插入到 DOM 树中。)
【解决方案2】:

虽然我发誓我曾经看过该规范(@Supersharp 提到的那个),但现在:

  • 允许对属性进行检查(适用于 Chrome、Firefox 和 Safari),所以getAttribute 可以
  • 正如预期的那样,属性的变异是被禁止的

好吧,也许我们确实应该将“增益”理解为专门指突变。

可以说 - 等等,但如果元素无法获得任何属性 - 显然没有什么可检查的。好吧,以下 sn-p 对我有用(在任何浏览器上):

class A extends HTMLElement {
  constructor() {
    super();
    console.log(this.getAttribute('data-some'));
  }
}

globalThis.customElements.define('x-a', A);

const e = document.createElement('x-a');
// console: null

const t = document.createElement('div');
t.innerHTML = '<x-a data-some="test"></x-a>';
// console: test

CodePen

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 2017-01-01
    • 2021-12-17
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多