内connectedCallback()
我的自定义元素的方法textContent
作为空字符串返回。
本质上我的代码可以归结为以下内容......
class MyComponent extends HTMLElement{
constructor() {
super()
console.log(this.textContent) // not available here, but understandable
}
connectedCallback() {
super.connectedCallback() // makes no difference if present or not
console.log(this.textContent) // not available here either, but why?!
}
}
customElements.define('my-component', MyComponent);
还有 HTML...
<my-component>This is the content I need to access</my-component>
从阅读有关connectedCallback()
听起来好像是在元素添加到 DOM 后调用它,所以我希望 textContent 属性应该有效。
我正在使用 Chrome 63 如果有帮助的话...
您面临的问题本质上与我们团队在当前项目中遇到的问题相同:
connectedCallback在 Chrome 中是这样的not保证孩子们被解析。具体来说,依靠儿童工作upgrade情况,但是不起作用如果浏览器解析元素时预先知道该元素。所以如果你把你的webcomponents.js
捆绑在末尾body
,它至少可靠地适用于您迄今为止拥有的静态文档(但如果您在之后以编程方式创建元素,仍然会失败DOMContentLoaded
使用 document.write(无论如何你都不应该这样做))。这基本上就是您发布的解决方案。
去把事情弄得更糟,自定义元素规范 v1 中没有保证子元素访问的生命周期挂钩.
因此,如果您的自定义元素依赖于子元素来设置(以及像您这样的简单文本节点)textContent
is子节点),这是我们经过一周的大量研究和测试后能够提取的内容(这也是 Google AMP 团队所做的):
class HTMLBaseElement extends HTMLElement {
constructor(...args) {
const self = super(...args)
self.parsed = false // guard to make it easy to do certain stuff only once
self.parentNodes = []
return self
}
setup() {
// collect the parentNodes
let el = this;
while (el.parentNode) {
el = el.parentNode
this.parentNodes.push(el)
}
// check if the parser has already passed the end tag of the component
// in which case this element, or one of its parents, should have a nextSibling
// if not (no whitespace at all between tags and no nextElementSiblings either)
// resort to DOMContentLoaded or load having triggered
if ([this, ...this.parentNodes].some(el=> el.nextSibling) || document.readyState !== 'loading') {
this.childrenAvailableCallback();
} else {
this.mutationObserver = new MutationObserver(() => {
if ([this, ...this.parentNodes].some(el=> el.nextSibling) || document.readyState !== 'loading') {
this.childrenAvailableCallback()
this.mutationObserver.disconnect()
}
});
this.mutationObserver.observe(this, {childList: true});
}
}
}
class MyComponent extends HTMLBaseElement {
constructor(...args) {
const self = super(...args)
return self
}
connectedCallback() {
// when connectedCallback has fired, call super.setup()
// which will determine when it is safe to call childrenAvailableCallback()
super.setup()
}
childrenAvailableCallback() {
// this is where you do your setup that relies on child access
console.log(this.innerHTML)
// when setup is done, make this information accessible to the element
this.parsed = true
// this is useful e.g. to only ever attach event listeners to child
// elements once using this as a guard
}
}
customElements.define('my-component', MyComponent)
<my-component>textNode here</my-component>
Update:很久以前 Andrea Giammarchi (@webreflection),自定义元素 polyfill 的作者document-register-element
(例如 Google AMP 正在使用),他是引入这种parsedCallback
到自定义元素的 API,已采用上述代码并创建了一个包html-parsed-element
从中,这可能会帮助您:
https://github.com/WebReflection/html-parsed-element
您只需从HTMLParsedElement
包提供的基类(而不是HTMLElement
)。该基类又继承自HTMLElement
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)