Open Fuzzyma opened 2 years ago
I guess you are referring to https://vuejs.org/guide/components/events.html#usage-with-v-model?
onUpdate:data
should be an event, not a prop.
@FloEdelmann v-on
is just syntactic sugar on top of v-bind
. For more advanced usage, it is very much required that I can specify the events as props. Vue usually even tells you, that you either have to declare emits or a prop with the event name prefixed with on
. So this is not hidden knowledge and very useful under some circumstances. Eslint should allow it. If you consider it bad style, than we could ofc create a new rule for it. But the current implementation of "vue/attribute-hyphenation" only has problems with FIXING. It doesn't report this kind of props as errors. Only "prop-name-casing" does and as said above, vue allows to define events like that in your props so its wrong to report it as error
For more advanced usage, it is very much required that I can specify the events as props. […] very useful under some circumstances
Why? Can you share an example?
vue allows to define events like that in your props so its wrong to report it as error
Vue also allows mixing camelCase
and kebab-case
for different props, but that still doesn't mean it's recommended or readable.
So this is not hidden knowledge
At least I didn't know about this.
Vue usually even tells you, that you either have to declare emits or a prop with the event name prefixed with
on
.
But I think in the documentation, only the "event" way is used and thus recommended, right? In https://vuejs.org/guide/components/props.html#mutating-object-array-props, the documentation states:
In most cases, the child should emit an event to let the parent perform the mutation.
@ota-meshi what's your opinion?
Why? Can you share an example?
The use case I use the most are those:
In both cases, the component could still be used with v-model without breaking anything
Vue also allows mixing camelCase and kebab-case for different props, but that still doesn't mean it's recommended or readable.
This is true, however, as I said: your rules already allow passing such a prop to a component. Only the fixer is broken. Defining such a prop yields an error but the error message is wrong. The prop is allowed. Maybe not recommended but definitely allowed. And it also follows the correct naming convention (pascal or kebap). So this rule should pass and not return an error.
At least I didn't know about this.
Its not something that you would use very often.
Vue usually even tells you, that you either have to declare emits or a prop with the event name prefixed with on.
That might be the case but again doesn't justify that the rules don't work correctly. The docs also got a few overhauls already. I think they mentioned it at some point. It's actually an essential part of how vue works under the hood
All in all, I don't see a reason not to allow it since only advanced users will ever do the props technically fulfill the requirements of the rules.
If the official documentation describes how to do that, could you share it?
If it's not in the documentation, I don't think you should do it. Because I don't think it's advanced users who do things that aren't documented. If the document is simply missing, open an issue to add the document.
@ota-meshi the rules remain broken. How is this in any way related to the docs?
I cannot enable these rules without fixing being broken and getting false positives with misleading error messages. That alone is a reason good enough to fix these rules / accept the pr
If it's not documented, I think it may be an unguaranteed behavior in the future. The vue/prop-name-casing
rule does not accept unguaranteed behavior.
However, you can do it even if it is not documented. You can also turn off the annoying eslint rule. You can also create an eslint plugin to do your favorite checks.
So using onClick
as prop is fine and passing :onClick
is also fine. Using @click
is fine as well.
But using onUpdate:modelValue
is not fine. Passing :onUpdate:modelValue
is fine but breaks fixing and using @update:modelValue
is perfectly valid?
This is not consistent.
If you want to restrict users from using onSomething
as prop (which is your main argument), make it an extra rule (name could be "prefer-emit"). But don't leave other rules inconsistent just because of that
If there is no documentation to explain it, the rule will not change it to support it. Thank you for your understanding.
@ota-meshi the rule DOES support ist!
I gave you good arguments, point out inconsistencies, discover misleading error messages and the only thing you repeat is "I can't find it in the docs". Using a prop named "onClick" is supported by your rule. So you alteady support event handlers as props. You also support passing "onUpdate:bla" without giving me any error message. It will just not make it kepap case automatically.
I get the feeling that you simply don't WANT
Using a prop named "onClick" is supported by your rule. So you alteady support event handlers as props.
That's just your interpretation. The rule doesn't care about whether a prop is used as an event handler or not. It just cares about casing. And it considers fooBar:baz
as not camelCase, so it complains. onClick
is definitely camelCase, so it doesn't complain.
I agree with your comment https://github.com/vuejs/eslint-plugin-vue/issues/1911#issuecomment-1154528373 though: The rules are inconsistent.
@ota-meshi maybe we should indeed allow/forbid :
characters and adjust the casing rules to support :
in prop names in both rules.
If naming with a colon is fairly common and there is a good reason, we should consider adding an option. However, if we expect it to be used as an event, other rules will need to be changed as well. For example, the vue/no-unused-properties
rule should mark onClick
prop as used if it was used in $emit('click')
.
For example, the
vue/no-unused-properties
rule should markonClick
prop as used if it was used in$emit('click')
.
No, because the function prop would really be unused in that case.
There would not be a real Vue event triggered by emit
, but it would be calling a function that is passed as a prop. Using a colon in the prop name is just a convention for "event handler props" if I understood @Fuzzyma correctly.
technically you can invoke a function passed as prop via emit (since its all the same stuff). So @ota-meshi has a point here.
If you think about render functions, you always pass down your event handlers as onSomething
and still expect them to work with emit. However, I didn't have any problems with "vue/no-unused-properties" yet. If it's in "vue3-recommended", shouldn't it have complained about my code?
The only reason colon exists in prop or event names at all is because vue decided to introduce the update:fooBar
methodology. It's the only place where I would ever use colons in props. e.g. onClick
is an event handler prop and doesn't have any colon in it.
I would even consider banning any other props with colons that don't follow the update:fooBar
-semantic because it is bound to special behavior in vue. However, that would need another round of thinking because technically nobody stops you from using any colons in your prop names at all
No, because the function prop would really be unused in that case.
Hmm. You are right. We may not need to change that rule. If it's just a naming issue, we may be able to add it as an option. (However, the default behavior should remain the same as it is now.)
If you really need that API for Vue core, I think you need to go ahead with the discussion on the next link.
If you really need that API for Vue core, I think you need to go ahead with the discussion on the next link.
The discussion seems to be about if $attrs should contain listeners but as props they are always there afaik. I will read into it some more, however. Sounds interesting.
I think adapting the rules above to streamline their behavior would clear the paths for potential other rule ideas that came up in this discussion
@ota-meshi could we probably reopen this issue? Especially after reading through your linked discussion, it seems like defining props the way I showed here seems to be even more common than I thought.
For now, I think it makes the most sense to add an option instead of allowing the colon by default.
However, if onUpdate:*
prop is the recommended usage, it should be allowed by default, but I still can't get that confirmation.
@ota-meshi I am just thinking, that event-handler-props generally seem to be a common thing (e.g. to be able to check if a listener was passed). The only difference here is the colon in the prop name.
However, onUdpate:modelValue
is the event-handler-prop that is used by v-model
automatically. That's why I think, it should be allowed.
Another reason why I think this should work is, that it is already allowed to pass those props to the component (because it is correctly parsed by the parser). And if that is allowed, defining those should be allowed, as well.
However, I am open to implementing an option that enables/disables props with columns. Would that be something that would make the PR megeable?
My thoughts... this seems to be a "code style" rule, rather than a "code validity" rule. i.e. you can use any prop name you want and it will work... this rule just enforces a particular naming style.
The way I see it, when Vue 3 introduced update:modelValue (or update:model-value) as a standard convention, the intent is that the colon is used as a separator, and camel/kebob style should be applied to the names that are separated by the colon.
IMO, the issue of whether the name is being used as a data property or event handler is irrelevant. The linter rule is there to enforce a certain property naming style, not how it's being used. And with Vue 3, the naming convention seems to support using a colon as a separator, whether using camel or kebob case style.
The way I see it, when Vue 3 introduced update:modelValue (or update:model-value) as a standard convention, the intent is that the colon is used as a separator, and camel/kebob style should be applied to the names that are separated by the colon.
I still disagree with that. The colon style was introduced only in the event name. I don't think introduced in prop name. However, you can access the event by declaring the same (similar) prop name as the event name, so use a colon for the prop. I don't think users want to use a colon for prop name for any other purpose.
If we only consider vue/prop-name-casing
rule, I think we need to add one of the following options:
onXXX
from the check.ignores
in vue/custom-event-name-casing
.https://eslint.vuejs.org/rules/custom-event-name-casing.html#options
The first option can be the default, depending on the conclusion, but the second option is disabled by default. If it's a naming style issue, I think the second option makes sense.
@ota-meshi but if it is not allowed as prop, the error message should be "colon is not allowed in prop" and not "prop should be camelCase". Beside that, in a render function you would write:
const foo = ref(0)
return () => h(Component, {
modelValue: foo.value,
'onUpdate:modelValue': (val) => foo.value = val
})
And that is already reality. The event handler is passed as prop and has a colon
I agree with @Fuzzyma points. The changes in the proposed PR are aimed at fixing the fixer, not checker.
Both cases onUpdate:modelValue
and :on-update:model-value
are currently allowed by eslint if I configure it correctly (specify kebab-case or camelCase props lint rule). The problem is that fixer will not do this conversion :onUpdate:modelValue <-> :on-update:model-value
automatically and will just complain instead. IMO this should be automatically fixable.
The PR is valuable and currently the absence of this feature in the fixer is a friction point for me when trying to enforce kebab-case props casing in my project. As far as I can see, it doesn't break anything and only improves fixer so it's in line with what is already allowed.
What rule do you want to change?
vue/prop-name-casing vue/attribute-hyphenation
Does this change cause the rule to produce more or fewer warnings?
Fewer
How will the change be implemented? (New option, new default behavior, etc.)?
New default behavior
Please provide some example code that this change will affect:
What does the rule currently do for this code?
This shows a warning for
'onUpdate:data'
because it is not considered camelCase. However, this is the normal description of an update handler defined via v-modelWhat will the rule do after it's changed?
It shouldn't warn. This is a valid prop and used if you want to have more control about the v-model cycle (e.g. awaiting a promise as in this example).
This could easily be fixed by treating
:
as an uppercase letter.Additional context
vue/attribute-hyphenation is related and should also be changed. It is impossible to pass a prop like
:on-update:model-value
because i will complain. However, its a valid prop! I am not sure if vue supportson-update
as replacement foronUpdate
. If not, it should be always allowed to writeonUpdate