自定义元素类型在脚本类型=模块中加载时报告 HTMLElement?
custom element type reports HTMLElement when loaded in script type=module?
我正在使用自定义元素,我注意到在一个案例中我无法访问实例的属性,如 var prop = myCustomElement.myPropery // undefined
中 属性 是在 [=44= 中定义的] 例如get myProperty() { blah }
.
当自定义元素在脚本中定义时,我将问题归结为 myCustomElement.constructor
中报告的内容(因此 prototype/instance 类型) type="module"对比没有模块类型。
这是一个非常简单的例子:
var test = document.getElementById ( "test" );
console.log ( test.mood, test.constructor );
<script type="module">
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
window.customElements.define ( "test-case",
class TestCase extends window.HTMLElement {
constructor () {
super ();
var frag = template.content.cloneNode ( true ),
shadow = this.attachShadow( { mode: "open" } );
shadow.appendChild ( frag );
}
get mood () {
return "Happy!";
}
} );
</script>
<test-case id="test"></test-case>
...并且没有模块类型
var test = document.getElementById ( "test" );
console.log ( test.mood, test.constructor );
<script>
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
window.customElements.define ( "test-case",
class TestCase extends window.HTMLElement {
constructor () {
super ();
var frag = template.content.cloneNode ( true ),
shadow = this.attachShadow( { mode: "open" } );
shadow.appendChild ( frag );
}
get mood () {
return "Happy!";
}
} );
</script>
<test-case id="test"></test-case>
这似乎很不对,这是故意的吗?
而且,假设需要使用一个模块,例如定义要在更大的组件或库中使用的自定义元素,是否有直接的方法来防止模块隐藏自定义元素的类型?
注意:我正在从最新的 Chrome (74.0.3729.157) 测试这个,还没有尝试过其他浏览器。
您需要等到元素被定义。
见CustomElementRegistry.whenDefined()
The whenDefined() method of the CustomElementRegistry interface
returns a Promise that resolves when the named element is defined.
customElements.whenDefined('test-case').then(
() => {
const test = document.getElementById("test");
console.log(test.mood, test.constructor);
}
);
<script type="module">
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
window.customElements.define ( "test-case",
class TestCase extends window.HTMLElement {
constructor () {
super ();
var frag = template.content.cloneNode ( true ),
shadow = this.attachShadow( { mode: "open" } );
shadow.appendChild ( frag );
}
get mood () {
return "Happy!";
}
} );
</script>
<test-case id="test"></test-case>
您的 non-module 脚本在模块脚本之前 运行。所以你只需要等到元素被定义但调用 customElements.whenDefined
:
https://devdocs.io/dom/customelementregistry/whendefined
在使用 customElements
或 HTMLElement
时也没有理由使用 window
。
customElements.whenDefined('test-case').then(
() => {
const test = document.getElementById ( "test" );
console.log ( test.mood, test.constructor );
}
);
<script type="module">
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
customElements.define ( "test-case",
class TestCase extends HTMLElement {
constructor () {
super ();
const frag = template.content.cloneNode ( true );
const shadow = this.attachShadow( { mode: "open" } );
shadow.appendChild ( frag );
}
get mood () {
return "Happy!";
}
}
);
</script>
<test-case id="test"></test-case>
我正在使用自定义元素,我注意到在一个案例中我无法访问实例的属性,如 var prop = myCustomElement.myPropery // undefined
中 属性 是在 [=44= 中定义的] 例如get myProperty() { blah }
.
当自定义元素在脚本中定义时,我将问题归结为 myCustomElement.constructor
中报告的内容(因此 prototype/instance 类型) type="module"对比没有模块类型。
这是一个非常简单的例子:
var test = document.getElementById ( "test" );
console.log ( test.mood, test.constructor );
<script type="module">
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
window.customElements.define ( "test-case",
class TestCase extends window.HTMLElement {
constructor () {
super ();
var frag = template.content.cloneNode ( true ),
shadow = this.attachShadow( { mode: "open" } );
shadow.appendChild ( frag );
}
get mood () {
return "Happy!";
}
} );
</script>
<test-case id="test"></test-case>
...并且没有模块类型
var test = document.getElementById ( "test" );
console.log ( test.mood, test.constructor );
<script>
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
window.customElements.define ( "test-case",
class TestCase extends window.HTMLElement {
constructor () {
super ();
var frag = template.content.cloneNode ( true ),
shadow = this.attachShadow( { mode: "open" } );
shadow.appendChild ( frag );
}
get mood () {
return "Happy!";
}
} );
</script>
<test-case id="test"></test-case>
这似乎很不对,这是故意的吗?
而且,假设需要使用一个模块,例如定义要在更大的组件或库中使用的自定义元素,是否有直接的方法来防止模块隐藏自定义元素的类型?
注意:我正在从最新的 Chrome (74.0.3729.157) 测试这个,还没有尝试过其他浏览器。
您需要等到元素被定义。
见CustomElementRegistry.whenDefined()
The whenDefined() method of the CustomElementRegistry interface returns a Promise that resolves when the named element is defined.
customElements.whenDefined('test-case').then(
() => {
const test = document.getElementById("test");
console.log(test.mood, test.constructor);
}
);
<script type="module">
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
window.customElements.define ( "test-case",
class TestCase extends window.HTMLElement {
constructor () {
super ();
var frag = template.content.cloneNode ( true ),
shadow = this.attachShadow( { mode: "open" } );
shadow.appendChild ( frag );
}
get mood () {
return "Happy!";
}
} );
</script>
<test-case id="test"></test-case>
您的 non-module 脚本在模块脚本之前 运行。所以你只需要等到元素被定义但调用 customElements.whenDefined
:
https://devdocs.io/dom/customelementregistry/whendefined
在使用 customElements
或 HTMLElement
时也没有理由使用 window
。
customElements.whenDefined('test-case').then(
() => {
const test = document.getElementById ( "test" );
console.log ( test.mood, test.constructor );
}
);
<script type="module">
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
customElements.define ( "test-case",
class TestCase extends HTMLElement {
constructor () {
super ();
const frag = template.content.cloneNode ( true );
const shadow = this.attachShadow( { mode: "open" } );
shadow.appendChild ( frag );
}
get mood () {
return "Happy!";
}
}
);
</script>
<test-case id="test"></test-case>