The attr fall-through overrides the value of prop
Vue version
3.3.4
Link to minimal reproduction
Steps to reproduce
open the link
What is expected?
show 456
What is actually happening?
show 123
System Info
No response
Any additional comments?
No response
I would say this is expected: the same happens with an attribute and one can disable it with inheritAttrs: false
. It's also a breaking change but I really don't think it's worth since it's less flexible than the current behavior
you can also use the .attr
modifier to prevent this /enforce the passed-through attribute be be applied as an HTML attribute, thereby not overriding the prop:
Please NOTE:
- This behavior is inconsistent to vue2 and we didn't documented in the docs.
- This kind of overriding prop behavior is unstable. If the user modifies the template of Comp.vue in the future (e.g. adding a
<div>
in the root), it may cause the attr to no longer fall through to Comp1.vue, and the rendering result may be different. This is something that is difficult to foresee in advance. It is also not easy to track down the root cause of problems.
It still look more convenient to me for the points mentioned above. The current behavior feels like an improvement as it's more predictable that having different behaviors for attrs and props
In principle, I agree with @edison1105 - strictly speaking, it's an undocumented behaviour and its unstable nature can, in edge cases, lead to subtle bugs in use's apps.
Practically speaking though, this behavior has been around for so long that "fixing" it now will inevitably break some existing userland code where that behavior is used on purpose by devs who understood the feature to work this way implicitly.
So what are our options:
- "Fix" it and risk breaking user's code.
- Add a runtime warning of some kind
- Document the behavior, while giving recommendations like:
When using fallthrough attributes, we recommend explicitly declaring them as attributes using
.attr
or DOM properties using.prop
in order to avoid a nested ancestor root component accidentally consuming them as a component prop".
We could combine this with a note about how we intend to change this behaviour in the next major - provided that we agree on wanting to do that and whenever we would do Vue 4, for which there are no current plans)
As a general note: Fallthrough attributes are a convenience feature that are a bit unstable by their nature. In a variation of edison's example, consider a component that has <input>
as the root element, and then a <label>
is added as the new root node to wrap the input properly. Now a id
fallthrough attribute will falsely be added to the <label>
instead of the input.
What about a feature flag?
something like inheritAttrs: 'avoid-props-override'
? (not attached to the specific name).
It seems to me it can't be a global flag (at least not exclusively) as it would easily lead to weird bugs in 3rd party components relying on it.
So it would have to be a guard implemented in each receiving component. Could work but feels cumbersome as you would likely want to add it to practically all of your components once you use it, to be consistent.