我很難理解HTML導入的特定行爲。我只是在進口內交換一行並獲得完全不同的輸出。
因此,這裏是我得到了什麼?
的index.html
<!DOCTYPE html>
<html>
<head>
<link rel="import" href="./element-a.html">
<link rel="import" href="./element-b.html">
<link rel="import" href="./element-c.html">
</head>
<body>
<element-a></element-a>
</body>
</html>
元素a.html
<template>
<element-b>
<element-c>Hi!</element-c>
</element-b>
</template>
<script>
console.log('registering a');
class ElementA extends HTMLElement {
constructor() {
super();
console.log('upgrading a');
const $template = this.constructor.ownerDocument.querySelector('template');
const $clone = $template.content.cloneNode(true);
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild($clone);
const $c = this.shadowRoot.querySelector('element-c');
const isDefined =() => console[$c.say ? 'debug' : 'error'](`say() is ${$c.say ? '': 'un'}defined`)
isDefined();
const undefined = this.shadowRoot.querySelectorAll(':not(:defined)');
const promises = [...undefined].map(el => customElements.whenDefined(el.localName));
console.log('undefined: ', undefined);
Promise.all(promises).then(() => {
console.log('ready');
isDefined();
});
}
}
ElementA.ownerDocument = document.currentScript.ownerDocument;
customElements.define('element-a', ElementA);
</script>
元素b.html
<template>
<slot></slot>
</template>
<script>
console.log('registering b');
class ElementB extends HTMLElement {
constructor() {
super();
console.log('upgrading b');
const $template = this.constructor.ownerDocument.querySelector('template');
const $clone = $template.content.cloneNode(true);
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild($clone);
}
}
ElementB.ownerDocument = document.currentScript.ownerDocument;
customElements.define('element-b', ElementB);
</script>
元件c.html
<template>
<slot></slot>
</template>
<script>
console.log('registering c');
class ElementC extends HTMLElement {
constructor() {
super();
console.log('upgrading c');
const $template = this.constructor.ownerDocument.querySelector('template');
const $clone = $template.content.cloneNode(true);
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild($clone);
}
say(words) {
console.log(words);
}
}
ElementC.ownerDocument = document.currentScript.ownerDocument;
customElements.define('element-c', ElementC);
</script>
我還創建了一個pen。現在有什麼困惑我:如果我輸入element-a
第一我得到這樣的輸出:
註冊
升級
說()是未定義
未定義:(2)[元素B,元素 - C]
註冊b
升級b
註冊ç
升級ç
準備
說()被定義
但是,如果我在最後導入它,我得到一個完全不同的註冊和升級的輸出和秩序。
註冊b
註冊Ç
登記
升級
升級b
升級Ç
說()被定義
未定義:[]
準備
說()是定義爲
這是爲什麼?我期望最後的輸出是始終發生的輸出。它與插槽/ Shadow DOM有什麼關係?
從https://w3c.github.io/webcomponents/spec/custom/#upgrades:請注意,只升級適用於文檔樹中的元素。未插入到文檔中的元素將保持未升級狀態。因此,在第二個示例中,它們都是首先註冊的,因爲「A」尚未出現在文檔中。 – ebidel
我明白了,但是我不明白導入的順序與此有關?特別是因爲在這兩種情況下'element-a'始終在文檔樹中。 – mzdr
'element-a'在開始的文檔中,但是'b'和'c'不是(直到'a'被註冊)。這兩個人立即註冊b/c你正在加載他們的進口。但只有在'a'導入將它們添加到文檔中時纔會升級它們。合理? – ebidel