New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Anonymous custom elements 匿名自定义组件 #842
Comments
In a recent post about custom element registration, I expressed support for an idea along these lines. Like @masx200, we've had to invent a means to auto-register component classes with generated names. As that post indicates, we almost never use registered component tags in our code — we create all components via their constructors, so registration of a tag for each class is undesirable overhead for us. It doesn't seem feasible (or even desirable) to actually remove the need for custom element tags, but I wonder whether it would be possible to have invocation of a component constructor trigger auto-registration of that class using a generated tag name if the class isn't already registered. E.g., // Can instantiate without explicit registration.
class MyElement extends HTMLElement {}
const myElement = new MyElement(); // works, implicitly registers class
// Can reference localName of implicitly-registered class
const tag = myElement.localName; // "my-element-a87f3ee9" or something
// The generated tag is usable.
const myElement2 = document.createElement(tag);
// Once implicitly registered, a class can't be explicitly registered.
customElements.define('my-element', MyElement); // throws |
I think #716 is a much better solution for this. Rather than take a name out of the global namespace, just register the elements you need in your scope. Then you can use whatever name you want, including a generated one (within some constraints, like element collaboration that depends on names). Emulating registry scopes by generating names is similar to emulating shadow dom by generating class names. It can work in some cases, but a real scope will be much better. |
You can try the "JavaScript" toolkit I wrote and randomly define the name. var mycom = class extends HTMLElement {};
const tag =RandomDefine(mycom);
var myele = new mycom(); var mycom = class extends HTMLDivElement {};
const tag =RandomDefine(mycom, "div");
var myele = new mycom(); interface Class {
new (): HTMLElement;
prototype: HTMLElement;
}
function RandomDefine(initclass: Class, extendsname?: string): string; |
@justinfagnani Scoped registries will be great! But they solve a different problem, no? The focus here is that having to learn and think about registries — whether global or scoped — adds conceptual load. Scoped registries increase (rather than decrease) the knowledge and code required to instantiate an element: class MyElement extends HTMLElement {}
const myRegistry = new CustomElementRegistry(window.customElements);
myRegistry.define('my-element', MyElement);
const myElement = new MyElement(); [I'm not entirely sure the above would actually work. The examples at #716 show the association of a scoped registry with a shadow root. If that's absolutely required — e.g., to avoid name conflicts with those in the global registry — then even the verbose code above wouldn't be possible to instantiate elements at the document level.] The main thing I'm trying to convey is that, over the past couple of years, I've come to realize that the number of situations in which I actually care about the tag name is small. In which the tag name is, at best, a side concern, it would be nicer to be able to just create the class and instantiate it. Addressing this is clearly not essential — we can work around the problem. But looking at other libraries on the web today that export classes, I can usually instantiate those classes immediately; no other bookkeeping is required. I'm just observing that the need to register classes at all makes working with custom element classes more complex. |
Similar request I posted at whatwg/html#4944 |
I think this is a wonderful idea. We have to determine how it should affect What about just not including the element in .innerHTML? inspector<div>
<#MyComponent>
<span/>
</#MyComponent>
</div> innerHTML<div>
<span></span>
</div> |
I have created a polyfill now and I think that we need a way to separate anonymous elements from named elements. The nicest solution here imo. is this: class MyAnonymousElement extends AnonymousElement {
// ...
} Link to proposal and polyfill: https://github.com/adrianhelvik/anonymous-custom-elements |
So the proposal here is to generate a random local name and avoid the call to |
Well, technically to not have a name. The random name is there out of necessity. A random name isn't that bad either I guess. |
How would not having a name work? (There's many more APIs than If it's a random name, why does it need to be added to the standard library? Seems easy enough to do yourself. |
@annevk I would like to do a write-up about the use cases (e.g. reusable component vs application development) and why "anonymous" custom elements make sense for these contexts. However, I will probably get to that after next week because of other work I have to finish next week. So I will be able to answer your question, but with a bit of a delay 😄 |
I started a write-up, but couldn't finish it before the Christmas vacation. Will finish it next year. |
An element tag name can also be important in CSS styling. So if the element has no name or random name, it can be hard to target it in any selectors. Is this something that people are okay to sacrifice? |
@trusktr Good point. Anonymous elements must have display: contents. |
What’s the difference between an Anonymous Custom Element and a regular ES class? |
It is a DOM node, but can only be created by calling I've done some shenanigans to polyfill innerHTML/outerHTML, as you can see if you open the Live preview in my proposal and check out document.body.innerHTML in the console. PS: Some nasty hacking is involved and void elements are not accounted for. |
To me, the main thing I love about Custom Elements is that it offers a standardized way for authors to extend the browser's functionalities in a declarative way. Just like when you add some form element to your HTML document, you magically get some dynamic functionalities. Adding JS to HTML essentially is to extend the browser's abilities, and I feel being able to do it declaratively is very important, it's the only way we can progressively enhance our webpages. HTML already has somewhat anonymous elements like @Component({
selector: 'div.my-element`,
})
export class MyElement extends HTMLElement {
// ...
} Edit: I just saw this, it seems very interesting: |
Oh thanks! I made that. :) That indeed could serve as an alternative in some cases but maybe not what the OP is asking for. More details (off topic)That's a little tool I made which is basically an alternative to the On the main topic, for what the OP is asking, I agree with @justinfagnani that custom element registries scoped to ShadowDOM is a better approach for encapsulation of naming and implementation. How would anonymous custom elements be represented in HTML? It seems this would make things like SSR (server-side rendering) more difficult to achieve. The more difficult it is, the more specific each solution will be which can cause fragmentation between different custom element libraries that end up having very specific requirements for things like SSR to work properly. As an example of the opposite, the Declarative-Custom-Elements proposal would bring some standardization to custom elements as far as representation in HTML, which would make it easier to create things like SSR, and make it easier for custom element libraries to have a chance at being compatible with each other (there are still issues, the community would still need to make its own standards on top of that proposal, but the community standards would simpler and smaller). |
I want to propose a new proposal to the W3C.
Anonymous custom elements
.
Why do custom components have to define a name? Defining names is easy to conflict. Modern front-end frameworks use
virtual
doms
, and the ability to directly writehtml
is too weak.Because you can't write functions or objects directly in
html
I hope I can use custom elements without
define
In case of using an constructor to create an anonymous custom component directly
.
Also want to create anonymous custom components without using
document.createElement
Under the current api, you can only randomly define names for custom components.Unable to get all custom components that have been defined
I also wrote a js library that randomly named custom components.
Https://github.com/masx200/custom-elements-random-define
The text was updated successfully, but these errors were encountered: