vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.6k stars 8.32k forks source link

It's not possible to access a kebab-cased attribute as camel-case and other way around in attrs #4998

Open sevilyilmaz opened 2 years ago

sevilyilmaz commented 2 years ago

Version

3.2.22

Reproduction link

sfc.vuejs.org/

Steps to reproduce

Parent.vue

<script setup>
import { ref } from 'vue'
import Comp from './Comp.vue';

const ariaLabel = 'This is an aria-label';
</script>

<template>
  <Comp aria-label="This is an aria-label" />
  <Comp :aria-label="ariaLabel" />
  <Comp :ariaLabel="ariaLabel" />
</template>

Comp.vue

<script setup>
import { ref, useAttrs, computed } from 'vue'

const attrs = useAttrs();
const hasKebabCaseAriaLabel = computed(() => Boolean(attrs['aria-label']));
const hasCamelCaseAriaLabel = computed(() => Boolean(attrs.ariaLabel));
</script>

<template>
  <div>
    <div>
      kebab-case attr: {{ hasKebabCaseAriaLabel }}
    </div>
    <div>
      camelCase attr: {{ hasCamelCaseAriaLabel }}
    </div>

    <hr />
  </div>
</template>

Output:

kebab-case attr: true
camelCase attr: false
---
kebab-case attr: true
camelCase attr: false
---
kebab-case attr: false
camelCase attr: true
<div aria-label="This is an aria-label"></div>
<div aria-label="This is an aria-label"></div>
<div aria-label="This is an aria-label"></div>

What is expected?

Vue should be able to infer an attribute regardless of is case as they are used camel-cased in the HTML.

aria-label in this example, will be used as camel-case in all three usages.

What is actually happening?

When aria-label is passed with kebab-case attrs.ariaLabel returns undefined and when it's passed with camel-case attrs['aria-label'] returns undefined.

posva commented 2 years ago

I would say this is expected because that's how HTML attributes and are not adapted like props are when it comes to their naming. Also, this would be a breaking change

sevilyilmaz commented 2 years ago

It's sad to hear it would be a breaking change because it's controversial to be able to pass attributes in both cases while creating elements but not possible to read them in the same way.

Here is an example to that uses both cases to create elements.

This would make library developers' lives easier.

ClassicOldSong commented 2 years ago

@posva That's not the case. In SVG elements, not only the attributes are case sensitive, even the tags them selves are. This is a fundamental problem with Vue and that's a reason why I choose to create my own framework.

LinusBorg commented 2 years ago

Not saying that there's no room to optimize SVG-related stuff, but I don't see how that's related to the specific issue here?

ClassicOldSong commented 2 years ago

Not saying that there's no room to optimize SVG-related stuff, but I don't see how that's related to the specific issue here?

You're not realizing that tags appear in html can have and do have case sensitive attributes and tag names, which vue have completely no way to deal with.

Not mentioning XML namespaces which vue relies on for its v-xxx directives, users just can't deal with custom namespaces using vue.

LinusBorg commented 2 years ago

Please open issues about these problems. They seem to be adjacent to the issue at hand, but not really related.

Also Vue deals fine with camelCase attributes in SVG, judging from a simple test, so you might have come across some edge case?

https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCB7IHJlZiB9IGZyb20gJ3Z1ZSdcblxuY29uc3QgbXNnID0gcmVmKCdIZWxsbyBXb3JsZCEnKVxuPC9zY3JpcHQ+XG5cbjx0ZW1wbGF0ZT5cbiAgPHN2ZyB2aWV3Qm94PVwiLTUwIC01MCAxMDAgMTAwXCIgd2lkdGg9XCIyNTBweFwiIGhlaWdodD1cIjI1MHB4XCI+XG4gICAgPHJlY3QgeD1cIjBcIiB5PVwiMFwiIHdpZHRoPVwiNTAlXCIgaGVpZ2h0PVwiNTAlXCIgLz5cbiAgPC9zdmc+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0ifQ==

ClassicOldSong commented 2 years ago

I'm aware of that Vue does handle SVG differently: it has a built-in list of tags and attributes that are marked as SVG related. That's a very stubborn way of telling if a tag should be svg: once SVG adds some new attributes to it and it's not on the built-in list, users will have no way but dirty hacks to get it working. One other way of the story is that most users just don't have the need to deal with SVGs and the part of code for handling SVGs are just built-in with no-way to strip them out for those who don't need them.

This is probably off-topic but I have to mention here:

The same thing applies to all other scenarios that Vue attemps to "take care" for users: Users won't have a chance to deal with custom namespaces/strange or non-standard runtimes/built-in keywords etc, and once users want to handle things more manually or more detailed, they will fail and have no way to solve the problem within the "beauty" of Vue.

Just think about the feeling of sitting on an automated vehicle whose computer went mad but you have no way to take over.