当自定义元素*和它的子元素*已被初始化时如何获得回调 [英] How to get a callback when a custom element *and it's children* have been initialized

查看:104
本文介绍了当自定义元素*和它的子元素*已被初始化时如何获得回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我嵌套自定义元素。我想让我的父定制元素使用它的子定制元素的原型的方法和属性。例如

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

ChildElement.getName = function(){
returnBob;
}

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

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

ParentElement.createdCallback = function(){
var self = this;
setTimeout(function(){
//这会记录'Bob',正确
console.log(self.childNodes [0] .getName());
},0 );

//爆炸 - 没有定义getName。
console.log(self.childNodes [0] .getName());
};

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

< parent-element>< child-element>< / child-element>< / parent-element>

正如内联所指出的,父级不能读取在子元素原型上定义的任何内容。它可以,如果它立即引发setTimeout;它只是需要等到这个元素的子节点也已经建立。

看来这是因为元素创建时的回调顺序,我认为这是因为如:


  • 父母的原型已设置(从HTMLElement到ParentElement)
  • 父母的createdCallback被称为

  • 父母的附加回叫称为

  • 孩子的原型已设置(从HTMLElement到ChildElement)

  • 孩子的createdCallback被称为

  • 孩子的attachedCallback被称为



createdCallback触发这一点是有道理的,但据我所知,当你所有的孩子都被创造出来的时候,根本没有可用的回调。我认为这意味着在使用子元素原型创建任何东西时都是不可能的,而无需使用setTimeout来等待整个页面完成呈现。



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



我相信自定义元素的设计目的是允许使用其他元素内容进行参数化,并且有效地不支持自定义元素在这个内容中是相当令人惊讶的。

这可以被认为是在创建自定义标签时访问儿童时未定义原型。然而,这个问题很糟糕,有很多例子,唯一的答案似乎实际上是一个实现错误,而不是一个解决方案(或者至少,它不再是当前的浏览器行为)


实际上,有很多不同的方法可以通过嵌套的自定义元素来实现这一点。



直接的方式

是为自己的 attachCallback 方法中的子元素调用的父元素添加自定义回调:

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

ChildElement.attachedCallback = function()
{
this.parentElement.childAttachedCallback()
}

在复杂情况下,您可以使用:


  • a Promise 由父级设置的对象并由一个或多个子级解析

  • 自定义事件fi红色,被父母抓住,
  • a MutationObserver 对象集用于观察父级子列表中的更改...
  • li>

I'm nesting custom elements. I'd like to have my parent custom element use methods and properties from its child custom element's prototype. E.g.

<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>

As noted inline, the parent cannot read anything that's defined on the child's element's prototype. It can if it fires an immediate setTimeout though; it just needs to wait until the child nodes of this element have also been set up.

It appears this happens because of the callback order during element creation, which I think is something like:

  • The parent's prototype is set (from HTMLElement to ParentElement)
  • The parent's createdCallback is called
  • The parent's attachedCallback is called
  • The child's prototype is set (from HTMLElement to ChildElement)
  • The child's createdCallback is called
  • The child's attachedCallback is called

That the createdCallback fires at this point makes sense, but as far as I can tell there's no callbacks available at all that fire when all your children have been created. I think that means it's impossible to ever do anything on creation that uses the prototype of your child elements, without using setTimeout to wait for the entire page to finish rendering.

Are there any callbacks or events you can listen to from the parent, to trigger only once the prototype of all your child nodes has also been set? Is there a different approach that would allow you to use structures like this? Is there anything else you can do, other than trigger a setTimeout?

I believed custom elements were designed to allow parameterization with other element content, and having custom elements effectively not supported in that content is quite surprising.

Arguably this could be considered a duplicate of Prototype not defined when accessing children on creation of custom-tag. However that question is poorly phrased, with broken examples, and the only answer appears to actually be an implementation bug, not a solution (or at least, it's no longer current browser behaviour)

解决方案

Actually, there are many different ways to achieve this with nested custom elements.

The direct way is to add a custom callback to the parent element that will be called by the child element from its attachedCallback method:

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

ChildElement.attachedCallback = function()
{
    this.parentElement.childAttachedCallback()
}

In a complex scenario you could use instead:

  • a Promise object set by the parent and resolve by one or more childs,
  • Custom Events fired by childs and caught by the parent,
  • a MutationObserver object set to observe changes in the parent's child list...

这篇关于当自定义元素*和它的子元素*已被初始化时如何获得回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆