最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Cannot access attributes of a custom element from its constructor - Stack Overflow

programmeradmin0浏览0评论

I'm trying to create a polyfill of sorts using the Custom Elements API for custom elements used by an in-game browser engine to display buttons and similar. However, I can't seem to access the element's attributes (eg. src, href ...) from within the constructor.

Here is an example:

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="" width="198" height="39" icon_src="" icon_width="34" icon_height="32" href="/" text="placekiten" color="#ffffff" size="18"></kw-button>

I'm trying to create a polyfill of sorts using the Custom Elements API for custom elements used by an in-game browser engine to display buttons and similar. However, I can't seem to access the element's attributes (eg. src, href ...) from within the constructor.

Here is an example:

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>

Share Improve this question edited Feb 15, 2017 at 13:56 link 2,4193 gold badges23 silver badges36 bronze badges asked Feb 15, 2017 at 13:44 Eva Lauren KellyEva Lauren Kelly 4131 gold badge4 silver badges15 bronze badges 2
  • 1 This seems to work fine as far as I can tell. Note that it's probably wise to delay work (like creating and loading an image) for the connectedCallback lifecycle event. – lonesomeday Commented Feb 15, 2017 at 13:56
  • @lonesomeday This is quite odd; it doesn't seem to run on my page (vivacity.fs3d.net) – Eva Lauren Kelly Commented Feb 15, 2017 at 13:58
Add a comment  | 

2 Answers 2

Reset to default 20

You cannot access the element DOM tree with querySelector() and appendChild(), and attributes with getAttribute() and setAttribute() in the constructor().

It's because at the time constructor() is called the custom element has no content yet.

You should defer that in the connectedCallback() method and it will be fine.

From the specs:

The element must not gain any attributes or children, as this violates the expectations of consumers who use the createElement or createElementNS methods.

In general, work should be deferred to connectedCallback as much as possible

Update as of 12me21 correction:

  • if the element was registered / defined before being parsed in HTML, the attributes won't be available
  • if the order of those is otherwise (parsed HTML as unknown, then define / upgrade) - they will

All in all I'd say now that since this is indeterminate to rely on this, well, exactly as it is warned by spec, I'd definitely refrain from accessing anything in the custom element c~tor, beside class' own definitions and alike.


Although I swear I've seen that spec once (the one @Supersharp mentioned), but nowadays:

  • inspection of the attributes is allowed (works for me on Chrome, Firefox and Safari), so getAttribute is OKAY
  • mutation of the attributes is, as expected, forbidden

Well, probably we indeed should read that 'gain' as specifically referring to mutation.

One could say - wait, but if element can't gain any attribute - obviously there is nothing to inspect. Well, the following snippet works for me (on any browser):

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

发布评论

评论列表(0)

  1. 暂无评论