简体   繁体   中英

Extending another custom element?

Trying to extend an custom element:

 class ABC extends HTMLDivElement { connectedCallback() { console.log('ABC here') } } customElements.define("x-abc", ABC, { extends: 'div' }) class XYZ extends ABC { connectedCallback() { console.log('XYZ here') } } customElements.define("x-xyz", XYZ, { extends: 'x-abc' })
 <div is="x-abc"></div> <div is="x-xyz"></div>

but getting this error:

 Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': "x-abc" is a valid custom element name

The err is confusing because it say 'is valid', not 'is not valid' !!

On the other hand FF says:

  Uncaught DOMException: CustomElementRegistry.define: 'x-xyz' cannot extend a custom element

I want to build hierarchy of custom elements.

The error may sound confusing at first, but actually it is very clear. The spec clearly defines that you can only extend built-ins using the is syntax. As it is currently designed, using ABC as a base class is definitely not the brightest idea (until you drop extending HTMLDivElement in favour of HTMLElement ).

You have not explained why you need to extend div elements, which is definitely not what you typically build a component hierarchy on. It is not even (and probably never will be) supported in Safari.

Instead, extend HTMLElement , and omit the is -syntax.

 class ABC extends HTMLElement { connectedCallback() { console.log('ABC here') } } customElements.define('x-abc', ABC) class XYZ extends ABC { connectedCallback() { super.connectedCallback(); console.log('XYZ here') } } customElements.define('x-xyz', XYZ)
 <x-abc></x-abc> <x-xyz></x-xyz>

If for whatever strange reason you need to keep extending HTMLDivElement (instead of HTMLElement which would be the proper way), here you go:

Just replace the {extends: 'x-abc'} part with {extends: 'div'} .

Both your components extend div (their defining tag name).

 class ABC extends HTMLDivElement { connectedCallback() { console.log('ABC here') } } customElements.define('x-abc', ABC, { extends: 'div' }) class XYZ extends ABC { connectedCallback() { super.connectedCallback(); console.log('XYZ here') } } customElements.define('x-xyz', XYZ, { extends: 'div' })
 <div is="x-abc"></div> <div is="x-xyz"></div>

Actually, the option-name extends:"xxx" is confusing. As the extended built-in element must be html-marked with the tag of that built-in (accompanied with the is attribute), this option does not determine the direct ancestor ("extending" it) (this is defined by the class-constructor-chain), rather it defines the tag-name, for which the given constructor (together with the whole chain) is used when parsing html/upgrading the element. Strictly speaking, it does extend that tag's class indeed, however not directly. The meaning "extends", is more related to the html is="xxxx" syntax. Think about it as it would have some name like basetag, builtintag, markuptag, builtinbase etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM