动态实例化web组件的方法之间的差异



web组件(仅针对此问题的自主自定义元素(可以通过多种方式"活过来";。

以下三个选项之间是否存在显著差异?

选项1:

const foo = document.createElement('foo-element');
document.body.appendChild(foo);

选项2:

const div = document.createElement('div');
div.innerHTML = '<foo-element></foo-element>'
const foo = div.firstElementChild;
document.body.appendChild(foo);

选项3:

const foo = new FooElement;
document.body.appendChild(foo);

我写了一些基于Karma/Mocha堆栈的单元测试,并用选项3创建了我的实例。

这是否足够,也就是说,我可以使用任一方法依赖于具有相同状态/行为的组件,或者是否有必要使用所有不同的实例化选项重复我的所有测试?

由于一个错误,我的一个web组件无法使用document.createElement进行实例化:

VM977:1 Uncaught DOMException: Failed to construct 'CustomElement':
The result must not have attributes
at <anonymous>:1:10

使用new可以毫无问题地实例化同一组件这一事实告诉我,在幕后,必须有显著的差异,尤其是new FooElementdocument.createElement('foo-element')之间的差异。

当然,我可以编写三个通用测试来测试所有三种实例化方式,但这足够了吗?

或者,我现有的所有测试都应该使用所有3个实例化选项来运行?

或者问不同的问题:

实例化后每个实例都完全一样吗?(假设没有错误(

如果使用CustomElementRegistry.define()方法将foo-element注册为自定义HTML元素,则3种方法之间的差异就会显现出来。根据我的实验,第二种方法不能利用注册自定义元素所提供的任何特殊处理。此外,第一种方法必须按照以下方式进行:

document.createElement("p", { is: "foo-element" });

其中我定义了CCD_ 7以扩展CCD_。

无论如何,一个例子可以更好地解释这一点。在下面的代码中,我定义了CCD_ 9以扩展CCD_;我是福">

// Create a class for the element
class FooElement extends HTMLParagraphElement {
constructor() {
// Always call super first in constructor
super();
this.innerText = 'I am foo';
}
}

// Define the new element (The CustomElementRegistry is available through the Window.customElements property):
customElements.define('foo-element', FooElement, { extends: 'p' });

现在执行以下代码段:

window.onload = function() {
class FooElement extends HTMLParagraphElement {
constructor() {
// Always call super first in constructor
super();
this.innerText = 'I am foo';
}
}
customElements.define('foo-element', FooElement, { extends: 'p' });
const div1 = document.createElement('div');
document.body.appendChild(div1);
const foo1 = document.createElement("p", { is: "foo-element" });
div1.appendChild(foo1);
const div2 = document.createElement('div');
document.body.appendChild(div2);
div2.innerHTML = '<foo-element></foo-element>';
const div3 = document.createElement('div');
document.body.appendChild(div3);
const foo3 = new FooElement();
div3.appendChild(foo3);
};
<body>
</body>

我们已经创建了所有三个元素,但只有口渴和第三个选项才能实现所需的特殊处理。如果您检查文本,您会发现实际的封闭元素实际上是<p>标记。

DOMException而言,无论您是否注册了元素,您展示的前两个方法都不应该导致异常。然而,如果FooElement不是合法节点(例如通过扩展HTMLParagraphElement创建的(,则第三种方法将抛出异常,如上例所示。所以,我需要更多关于你的例外情况的信息。

更新

这里,类FooElement不是从标准元素继承的,并且抛出了一个异常:

window.onload = function() {
class FooElement {
constructor() {
}
}
const div3 = document.createElement('div');
document.body.appendChild(div3);
const foo3 = new FooElement();
div3.appendChild(foo3);
};
<body>
</body>

相关内容

最新更新