I try to get a html custom element to work:
When viewing the following example in the browser I must conclude that this.dataset.text
attribute in the constructor()
is:
- present before the script defining the custom element
- empty after the script defining the custom element
<html>
<head>
<title>myimage</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>
before custom element definition: <my-element data-text="Replaced and works as expected">Not Replaced</my-element>
</div>
<script>
class MyElement extends HTMLElement {
constructor() {
super();
this.text_attribute= this.dataset.text;
}
connectedCallback() {
if (this.text_attribute) {
this.innerText = this.text_attribute;
}
}
}
customElements.define('my-element', MyElement);
</script>
<div>
after custom element definition: <my-element data-text="Replaced">Not Replaced</my-element>
</div>
</body>
</html>
This seems to be a common behavior in chrome and Firefox. I can provide some more facts:
- the
this.dataset.text
is always present inconnectedCallback()
- accessing the
text
-attribut viathis.getAttribute('data-text')
does behave in the same way as above
Can anyone explain the purpose of this seemingly buggy behavior?
CodePudding user response:
This isn't buggy behavior.
Your first <my-element>
is processed by the DOM parser before you define it.
Thus all attributes are known (in the DOM) when the constructor
executes.
In general you don't access DOM in the constructor
; as it also runs when you do:
let foo = document.createElement("my-element"); // absolutly no DOM created
Here is a trimmed down example:
<style>
my-element { display:block }
</style>
<my-element id="FOO"> ONE </my-element>
<script>
customElements.define('my-element', class extends HTMLElement {
constructor() {
super();
document.body.append(` ► constructor id:${this.id} ◄ `);
}
connectedCallback() {
document.body.append(` ► connected id:${this.id} ◄ `);
}
});
</script>
<my-element id="BAR"> TWO </my-element>
<my-element id="BAZ"> THREE </my-element>
NOTE
How
FOO
innerHTML is written (because it was parsed) to the DOM before itsconstructor
runsHow
BAR
andBAZ
constructor run before itsinnerHTML
is written to the DOM
and theid
value doesn't exist yetI have seen many courses where they "save" you from this standard behavior by executing the
<script>
async, thus after all DOM is parsed. They don't understand the technology...