如何在调用任何构造函数之前定义所有自定义元素?
How to define all custom elements before any constructors are called?
我有两个自定义元素:One
和 Two
。 One
有一个功能。 Two
具有 One
的 child 并尝试在其构造函数中调用该函数。它说如果我在 One
之前在 Two
上调用 customElements.define()
,则该函数不存在。但是,如果我在 Two
之前定义 One
,它就可以正常工作。
在我的实际项目中,我无法控制它们的定义顺序,默认情况下它们的定义顺序是错误的。
我尝试调用 connectedCallback()
中的函数,但这也失败了。
具体什么时候调用构造函数?
有什么方法可以确保它们在调用任何构造函数之前都已定义?
class One extends HTMLElement {
constructor() {
super()
console.log('one constructor')
}
myFunc() {
console.log('it worked!')
}
}
class Two extends HTMLElement {
constructor() {
super()
console.log('two constructor')
this.innerHTML = '<my-one></my-one>'
this.myOne = document.querySelector('my-one')
// this part fails
this.myOne.myFunc()
}
connectedCallback() {
// this also fails
this.myOne.myFunc()
}
}
// this works
// customElements.define("my-one", One)
// customElements.define("my-two", Two)
// this breaks
customElements.define("my-two", Two)
customElements.define("my-one", One)
<my-two></my-two>
这是关于 Web 组件的生命周期以及标签何时从 HTMLUnknownElement
升级到您的实际组件
分两步定义组件。
1) class 的定义
2) 调用 customElements.define
是的,这两个可以写在一起:
customElements.define('dog-food', class extends HTMLElement{});
但是 class 定义仍然发生在 customElements.define
被调用之前。
只有在发生以下两种情况时,元素才会升级为自定义元素:
1) 自定义元素必须使用 customElements.define
和
2) 自定义元素必须
1) 使用 document.createElement
或 new MyElement
实例化
2) 被添加到 DOM 树
此示例将元素放入 DOM,但未定义 1 秒。
我在定义之前显示构造函数,然后在定义之后再次显示它。
class One extends HTMLElement {
constructor() {
super();
console.log('one constructor');
}
connectedCallback() {
this.innerHTML = "I have upgraded";
}
}
let el = document.querySelector('my-one');
setTimeout(() => {
customElements.define("my-one", One);
console.log('after: ', el.constructor.toString().substr(0,30));
}, 1000);
console.log('before: ', el.constructor);
<my-one>I am just a simple element</my-one>
在您的代码中,您使用 innerHTML
到 "load" <my-one>
。但是由于 <my-two>
可能不会 "really" 在调用构造函数时 DOM 中,因此 innerHTML
不会在 DOM 中,因此, <my-one>
还不会升级。
您可以做的一件事是等待 <my-two>
组件真正放入 DOM,方法是等待更改 connectedCallback
函数中的 innerHTML
:
class One extends HTMLElement {
constructor() {
super();
console.log('one constructor');
}
myFunc() {
console.log('it worked!');
}
}
class Two extends HTMLElement {
constructor() {
super();
console.log('two constructor');
}
connectedCallback() {
this.innerHTML = '<my-one></my-one>';
setTimeout(() => {
this.myOne = document.querySelector('my-one');
this.myOne.myFunc();
});
}
}
customElements.define("my-two", Two)
customElements.define("my-one", One)
<my-two></my-two>
您会注意到我仍然必须将对 <my-one>
中函数的调用放入 setTimeout
调用中。这是因为在您的 connectedCallback
函数存在之前,<my-one>
元素无法升级。升级需要一个机会运行,它不会运行在你的函数中间。
另一种方法是直接调用 <my-one>
的构造函数:
class One extends HTMLElement {
constructor() {
super();
console.log('one constructor');
}
connectedCallback() {
this.innerHTML = "one";
}
myFunc() {
console.log('it worked!');
}
}
class Two extends HTMLElement {
constructor() {
super();
console.log('two constructor');
}
connectedCallback() {
customElements.whenDefined('my-one').then(() => {
this.myOne = document.createElement('my-one');
this.append(this.myOne);
this.myOne.myFunc();
});
}
}
customElements.define("my-two", Two);
customElements.define("my-one", One);
<my-two></my-two>
在这里您会注意到我必须添加对 customElements.whenDefined
的调用。这将等到 <my-one>
在尝试实例化之前实际定义。一旦它被定义,你就可以创建它并立即调用成员函数。
最后一件事。在 Web 组件的构造函数中,有关于您应该做什么和不应该做什么的规则。它们在这里定义 https://w3c.github.io/webcomponents/spec/custom/#custom-element-conformance
但我要指出的一件事是,您不应该触及或更改构造函数中的任何属性或子元素。主要是因为构建Web Component 时没有属性或任何子元素。这些都是事后更改和添加的。
我有两个自定义元素:One
和 Two
。 One
有一个功能。 Two
具有 One
的 child 并尝试在其构造函数中调用该函数。它说如果我在 One
之前在 Two
上调用 customElements.define()
,则该函数不存在。但是,如果我在 Two
之前定义 One
,它就可以正常工作。
在我的实际项目中,我无法控制它们的定义顺序,默认情况下它们的定义顺序是错误的。
我尝试调用 connectedCallback()
中的函数,但这也失败了。
具体什么时候调用构造函数?
有什么方法可以确保它们在调用任何构造函数之前都已定义?
class One extends HTMLElement {
constructor() {
super()
console.log('one constructor')
}
myFunc() {
console.log('it worked!')
}
}
class Two extends HTMLElement {
constructor() {
super()
console.log('two constructor')
this.innerHTML = '<my-one></my-one>'
this.myOne = document.querySelector('my-one')
// this part fails
this.myOne.myFunc()
}
connectedCallback() {
// this also fails
this.myOne.myFunc()
}
}
// this works
// customElements.define("my-one", One)
// customElements.define("my-two", Two)
// this breaks
customElements.define("my-two", Two)
customElements.define("my-one", One)
<my-two></my-two>
这是关于 Web 组件的生命周期以及标签何时从 HTMLUnknownElement
升级到您的实际组件
分两步定义组件。
1) class 的定义
2) 调用 customElements.define
是的,这两个可以写在一起:
customElements.define('dog-food', class extends HTMLElement{});
但是 class 定义仍然发生在 customElements.define
被调用之前。
只有在发生以下两种情况时,元素才会升级为自定义元素:
1) 自定义元素必须使用 customElements.define
和
2) 自定义元素必须
1) 使用 document.createElement
或 new MyElement
实例化
2) 被添加到 DOM 树
此示例将元素放入 DOM,但未定义 1 秒。
我在定义之前显示构造函数,然后在定义之后再次显示它。
class One extends HTMLElement {
constructor() {
super();
console.log('one constructor');
}
connectedCallback() {
this.innerHTML = "I have upgraded";
}
}
let el = document.querySelector('my-one');
setTimeout(() => {
customElements.define("my-one", One);
console.log('after: ', el.constructor.toString().substr(0,30));
}, 1000);
console.log('before: ', el.constructor);
<my-one>I am just a simple element</my-one>
在您的代码中,您使用 innerHTML
到 "load" <my-one>
。但是由于 <my-two>
可能不会 "really" 在调用构造函数时 DOM 中,因此 innerHTML
不会在 DOM 中,因此, <my-one>
还不会升级。
您可以做的一件事是等待 <my-two>
组件真正放入 DOM,方法是等待更改 connectedCallback
函数中的 innerHTML
:
class One extends HTMLElement {
constructor() {
super();
console.log('one constructor');
}
myFunc() {
console.log('it worked!');
}
}
class Two extends HTMLElement {
constructor() {
super();
console.log('two constructor');
}
connectedCallback() {
this.innerHTML = '<my-one></my-one>';
setTimeout(() => {
this.myOne = document.querySelector('my-one');
this.myOne.myFunc();
});
}
}
customElements.define("my-two", Two)
customElements.define("my-one", One)
<my-two></my-two>
您会注意到我仍然必须将对 <my-one>
中函数的调用放入 setTimeout
调用中。这是因为在您的 connectedCallback
函数存在之前,<my-one>
元素无法升级。升级需要一个机会运行,它不会运行在你的函数中间。
另一种方法是直接调用 <my-one>
的构造函数:
class One extends HTMLElement {
constructor() {
super();
console.log('one constructor');
}
connectedCallback() {
this.innerHTML = "one";
}
myFunc() {
console.log('it worked!');
}
}
class Two extends HTMLElement {
constructor() {
super();
console.log('two constructor');
}
connectedCallback() {
customElements.whenDefined('my-one').then(() => {
this.myOne = document.createElement('my-one');
this.append(this.myOne);
this.myOne.myFunc();
});
}
}
customElements.define("my-two", Two);
customElements.define("my-one", One);
<my-two></my-two>
在这里您会注意到我必须添加对 customElements.whenDefined
的调用。这将等到 <my-one>
在尝试实例化之前实际定义。一旦它被定义,你就可以创建它并立即调用成员函数。
最后一件事。在 Web 组件的构造函数中,有关于您应该做什么和不应该做什么的规则。它们在这里定义 https://w3c.github.io/webcomponents/spec/custom/#custom-element-conformance
但我要指出的一件事是,您不应该触及或更改构造函数中的任何属性或子元素。主要是因为构建Web Component 时没有属性或任何子元素。这些都是事后更改和添加的。