如何在自定义元素*及其子元素*已初始化时获取回调

Tim*_*rry 6 html html5 prototype custom-element

我正在嵌套自定义元素.我想让我的父自定义元素使用其子自定义元素原型中的方法和属性.例如

<script>      
var ChildElement = Object.create(HTMLElement.prototype);

ChildElement.getName = function () {
  return "Bob";
}

document.registerElement("child-element", { 
  prototype: ChildElement
});

var ParentElement = Object.create(HTMLElement.prototype);

ParentElement.createdCallback = function () {
  var self = this;
  setTimeout(function () {
    // This logs 'Bob', correctly
    console.log(self.childNodes[0].getName());  
  }, 0);

  // This explodes - getName is not defined.
  console.log(self.childNodes[0].getName());
};

document.registerElement("parent-element", { 
  prototype: ParentElement
});
</script>

<parent-element><child-element></child-element></parent-element>
Run Code Online (Sandbox Code Playgroud)

如内联所述,父级无法读取子元素原型上定义的任何内容.它可以,如果它立即触发一个setTimeout; 它只需要等到这个元素的子节点也被设置好了.

看起来这是因为元素创建过程中的回调顺序,我认为是这样的:

  • 设置父级的原型(从HTMLElement到ParentElement)
  • 调用父级的createdCallback
  • 调用父级的attachCallback
  • 设置了孩子的原型(从HTMLElement到ChildElement)
  • 调用孩子的createdCallback
  • 调用孩子的attachCallback

在这一点上,createdCallback触发是有道理的,但据我所知,当你所有的孩子都被创建时,根本没有可用的回调.我认为这意味着不可能在使用子元素原型的创建上做任何事情,而不使用setTimeout等待整个页面完成渲染.

是否有任何可以从父级监听的回调或事件,只有在设置了所有子节点的原型后才会触发?是否有一种不同的方法可以让你使用这样的结构?除了触发setTimeout之外,还有什么可以做的吗?

我认为自定义元素的设计允许使用其他元素内容进行参数化,并且在该内容中有效地不支持自定义元素是非常令人惊讶的.

可以说,这可以被认为是在创建custom-tag时访问子节​​点时未定义Prototype的副本.然而,这个问题的措辞很差,破坏的例子,唯一的答案似乎实际上是一个实现错误,而不是解决方案(或者至少,它不再是当前的浏览器行为)

Sup*_*arp 5

实际上,有许多不同的方法可以通过嵌套自定义元素来实现此目的。

直接的方法是向父元素添加自定义回调,子元素将通过其方法调用该回调attachedCallback

ParentElement.childAttachedCallback = function ()
{
    console.log( this.childNodes[0].getName() )
}

ChildElement.attachedCallback = function()
{
    this.parentElement.childAttachedCallback()
}
Run Code Online (Sandbox Code Playgroud)

在复杂的场景中,你可以使用:

  • Promise由父级设置并由一个或多个子级解析的对象,
  • 由孩子触发并由父母捕获的自定义事件,
  • MutationObserver设置为观察父级子级列表中的变化的对象 ...