JS自定义元素获取内部HTML

时间:2019-03-18 06:04:52

标签: javascript html html5 web-component shadow-dom

我们有这样定义的自定义元素...

<my-button>
   Submit
</my-button>

和标准的customElements定义

class MyButton extends HTMLElement{
   constructor(){
      super();
      // our custom code...
      this.innerHTML = ''; // ??? where did the 'Submit' go?
   }
}

...

customElements.define('my-button',MyButton);

问题在于,当尝试获取innerHTML时,我们知道我们可以做类似DOMContentLoadedwindow.onload的事情。

,但有时我们想使用代码动态地动态创建“我的按钮” 。并在添加后使其“呈现” ...

是否有标准方法可以做到这一点?它与connectedcallback()和其他“已连接”功能有关吗?

谢谢!

请注意-我已尝试使用connectedCallback()作为可能的解决方案,但这不能解决问题。

1 个答案:

答案 0 :(得分:0)

关于Web组件的构造函数中可以做什么和不能做什么的一组规则。他们在下面。

但是请考虑一下:

可以通过以下三种方式之一创建组件:

  1. 初始页面的一部分/使用innerHTML:当浏览器加载页面或使用innerHTML时,您可以在页面加载或innerHTML的一部分中向组件添加属性和子代。 / li>
parent.innerHTML = '<super-hero name="Thor"><super-weapon value="Mjolnir"></super-weapon></my-comp>'.
  1. 您可以调用document.createELement创建一个元素。在创建元素之前,不能添加属性或子元素。
let superHero = document.createElement('super-hero');
let superWeapon = document.createElement('super-weapon');
superHero.setAttribute('name', 'Thor');
superWeapon.setAttribute('value',  'Mjolnir');
superHero.appendChild(superWeapon);
parent.appendChild(superHero)
  1. 您可以使用new实例化对象。就像document.createElement一样,您必须等到元素创建之后才能添加属性和子元素。
let superHero = new SuperHero();
let superWeapon = new SuperWeapon();
superHero.setAttribute('name', 'Thor');
superWeapon.setAttribute('value',  'Mjolnir');
superHero.appendChild(superWeapon);
parent.appendChild(superHero)

一旦创建了组件,就会将其添加到DOM中,这就是调用组件的connectedCallback的时候。

所有这三种方式实际上都可以归结为使用new进行实例化。 document.createElement调用CustomElementRegistry.get获取该元素的构造函数,然后使用new创建该对象。

然后innerHTML解析HTML,然后调用document.createElement或使用new创建对象。

但是,这样做时,调用元素的构造函数时没有属性或子级。实际上,调用connectedCallback时可能没有任何子代或属性。这是在规范中添加observedAttributesattributeChangedCallback的原因之一。

规范中缺少的一件事是知道有人在将组件添加到DOM之前或之后添加或更改了子代。但是,如果您真的想知道孩子什么时候变,可以使用MutationObserver

这就是为什么构造函数中不存在子代或属性的原因。他们还没有添加蜜蜂。

Now on to the rules:

  

创作自定义元素构造函数时,作者必须遵守以下符合性要求:

     
      
  • 对super()的无参数调用必须是构造函数主体中的第一条语句,以便在运行任何其他代码之前建立正确的原型链和该值。

  •   
  • return语句一定不能出现在构造函数体内的任何地方,除非它是一个简单的提前返回(返回或返回此语句)。

  •   
  • 构造函数不得使用document.write()或document.open()方法。

  •   
  • 不得检查元素的属性和子元素,因为在非升级情况下将不存在元素,而依靠升级将使元素的可用性降低。

  •   
  • 该元素不得获得任何属性或子元素,因为这违反了使用createElement或createElementNS方法的消费者的期望。

  •   
  • 通常,应将工作尽可能地推迟到connectedCallback进行,尤其是涉及获取资源或渲染的工作。但是,请注意,connectedCallback可以被调用多次,因此,任何真正一次性的初始化工作都需要保护措施,以防止其运行两次。

  •   
  • 通常,应使用构造函数来设置初始状态和默认值,并设置事件侦听器和可能的影子根。

  •   
     

在元素创建过程中直接或间接地检查了其中的几个要求,如果不遵循这些要求,将导致无法通过解析器或DOM API实例化自定义元素。