Skip to content
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

Attributes are lost when using native customElements. #12584

Open
LoveVin opened this issue Dec 20, 2024 · 4 comments
Open

Attributes are lost when using native customElements. #12584

LoveVin opened this issue Dec 20, 2024 · 4 comments

Comments

@LoveVin
Copy link

LoveVin commented Dec 20, 2024

Vue version

3.5.13

Link to minimal reproduction

https://github.com/LoveVin/vue3-issue-demo

Steps to reproduce

I need to customize a web component. It has been working fine in previous Vue 2 projects, but I’m encountering issues when running it in a Vue 3 project.

After troubleshooting, I found that if I assign a value to this.name within the constructor of the custom element class, the name attribute is lost when the custom component is rendered on the page. The source code is <template> <aa-bb name="123"></aa-bb> </template>, but in the browser, it renders as <aa-bb data-v-7a7a37b1></aa-bb>, with the name attribute missing. This does not happen in Vue 2 projects.

The issue can be reproduced with the vue2-demo and vue3-demo created using Vite. You can find the compressed packages below. After downloading and installing them, the issue can be replicated.

I have also verified that the same issue occurs with Vue CLI. Using CDN to load Vue does not have this issue, nor does a native project. Therefore, I suspect it might be related to the Vue single-file component template packages.

Because this is a TypeScript project, when defining class properties, it’s necessary to initialize them within the constructor. As a result, the properties that are initialized later cannot be found.

demo.zip

What is expected?

<aa-bb name="123" data-v-7a7a37b1></aa-bb>

What is actually happening?

<aa-bb data-v-7a7a37b1></aa-bb>

System Info

System:
    OS: macOS 13.5 arm64 Apple M1 Pro
 Binaries:
    Node: 20.18.0
 npmPackages:
    vue: ^3.5.13 => 3.5.13

Any additional comments?

Why is this happening? Is it a bug in some of the Vue 3 compilation packages? Can it be fixed?

@edison1105
Copy link
Member

edison1105 commented Dec 23, 2024

use the ^ prefix to set the property as an attribute.

<aa-bb ^name="111" age="22"></aa-bb>

see Playground

or remove this.name = ''
see Playground

There is an inconsistency in attribute handling between Vue 2 and Vue 3. Vue 2 uses setAttribute(key, value), while Vue 3 uses this[key] = value if the element defines a key (key in el). When the attribute is prefixed with ^, setAttribute will be used.

@LoveVin
Copy link
Author

LoveVin commented Dec 23, 2024

@edison1105 "Why should I change the way native custom tags are used, and it's unreasonable to ask users to add a ^ prefix when assigning attributes to custom tags within a Vue3 project. You mentioned that this is an issue with Vue3's handling method. Is this a bug in Vue3? Vue3 should not affect the definition and usage of native custom tags."

@lejunyang
Copy link

lejunyang commented Dec 24, 2024

For custom elements, I think current modern frameworks share a common sense of assigning the data as property other than attribute, if that property exists on the element.
I can see React does this too for your demo
We can also check each framework's behavior details in Custom Elements Everywhere too

I think it's author's responsiblity to reflect property to attribute in custom elements if they want to use both property and attribute

@kleinfreund
Copy link
Contributor

I think it's author's responsiblity to reflect property to attribute in custom elements if they want to use both property and attribute

While it's the custom element author's responsibility to handle how IDL and content attributes reflect each other in the CE, there can be no argument about whether it's legitimate that custom elements can have both IDL and content attributes and have both use completely different reflection behavior.

HTML is the precedent for this: there are content attributes that reflect their IDL attributes (e.g. id, name on form controls) but generally content attributes don't reflect IDL attributes. It's rather more common that IDL attributes reflect content attributes.

In other words: it's completely up to a custom element to define its interface and that includes whether things are configurable via content and/or IDL attributes. Vue must be able to support both (and it does) and I also agree that setting name="test" should set the content attribute of a CE, not its IDL attribute (even if no content attribute should be used by the CE as a CE can't even really define its content attributes explicitly). If anything, it should be the IDL attribute setting in templates that should have a special syntax: after all, HTML has that very syntax for setting content attributes and no syntax at all for setting IDL attributes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants