-
Notifications
You must be signed in to change notification settings - Fork 546
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
Attr fallthrough behavior #137
Conversation
BREAKING CHANGE: adjust attr fallthrough behavior Updated per pending RFC vuejs/rfcs#137 - Implicit fallthrough now by default only applies for a whitelist of attributes (class, style, event listeners, a11y attributes, and data attributes). - Fallthrough is now applied regardless of whether the component has explicitly declared props. (close #749)
Would it be possible to align with the HTML spec and apply implicit fallthrough for all the Global attributes? The problem with a custom whitelist is that it's Vue-specific. You'll have to memorize it and there's no way to opt-out of this. Otherwise you'll encounter weird behaviour and won't be able to quickly tell what went wrong. For all the people who are familiar with HTML, Global attributes are a known thing and they know how they behave. I think it can be confusing for people to see when
Could you elaborate a bit more why this rule is important? The only problem I see with this are And lastly adding structured data markup would be much easier with this change since it's not tied to component internals. |
You can opt-out with |
You don't have to know the whole list by heart, but you'll be confident that everything that is global in HTML is global in Vue as well. "A known thing" was not about knowing every little detail about this list. It was about being familiar with the concept of it. Everyone who worked with HTML knows how a
How are people working with |
Yes you do need to know it, because you could use a global property without knowing it is one, ending up in unexpected behavior when using optional props. And it's very difficult to debug.
One thing is working with HTML and something else is being familiar with it. The point is the public varies and you cannot expect them to know all of the global attributes. I hope that makes more sense on why using the whole list of global attributes is not a good idea |
The potential issue with including a global attribute like const Foo = props => h('div', `id: ${props.id}`) And didn't expect On the contrary, when users rely on the fallthrough behavior, they are always intentionally doing so. If they expect an attribute to fallthrough but it didn't, it is easier for them to notice and figure out why. It is also technically possible for us to warn against an attribute that failed to fallthrough and wasn't accessed during render. Some additional points:
|
First of all, thanks for the detailed answer!
My assumption is that if it's requested like
I would like to note that you'll have to memorize this list only in case you have never used global properties. If you want to use a global property chances are you already know it's global. With the whitelist you'll have to limit the global properties you already know to a Vue-specific list.
This to me is as confusing as an
In the same sense any new built-in HTML element is a breaking change for Vue, but that doesn't prevent us from using those in templates.
I agree that some properties just don't make sense on a component at a first glance, but even with Even if the idea of Global attributes doesn't get any traction I'd like to propose some attributes that I think should have a fallthrough behaviour:
|
The whole reason we are introducing the whitelist is to support such usage (as proposed in Optional Props Declaration).
It is useful for simple one-off components. React works like that without much issue. Also with TypeScript you can annotate the props type without having to use the runtime declaration. In fact, TypeScript users will likely prefer annotating prop types with TS interfaces rather than the runtime JavaScript options.
Because in the context of styling components,
I bet a fair share, if not most of the devs using
ARIA/a11y is an important but often overlooked aspect of web development, which is why Vue as a framework should provide APIs that facilitate easier a11y best practices. If the whitelist can lead more devs to learn about a11y then it's a good thing.
That's true, but doesn't mean we have to introduce more of such cases when we can avoid it. For the suggestion of additional attributes, the reason for not including them is because they are mostly used on content, not components. If you have control over the components you are authoring, then you can always just add them directly in your own components. Fallthrough is typically used on 3rd party components you don't have control over, and these 3rd party components are almost always reusable, utility components. If they are used to display content, they will accept content via slots - which is controlled by you. The only exception is probably I can sense most of your objections root from the idea that a whitelist may lead to confusion when things don't work because it's not in the whitelist, but as we agree that the whole global attributes list doesn't make sense, then I think it's best to keep the whitelist minimal for only ones with high probability of being needed for fallthrough. |
I want to mention that |
There's also a |
I'm currently divided about While it's a global attribute, By the way, how are conflicts between explicit attributes in the root handled? I suppose Given a component <template>
<div role="button" style="text-decoration: underline; color: green">
<slot/>
</div>
</template> If it's consumed like this: <Comp role="link" style="color: red">
Content
</Comp> Should it render like option 1 or 2 below? <!--- Option 1: Final word by component provider -->
<div role="button" style="text-decoration: underline; color: green">
Content
</div>
<!-- Option 2: Final word by component consumer -->
<div role="link" style="text-decoration: underline; color: red">
Content
</div> I'm more inclined to option 1 (final word by component provider). |
What about |
I'm also not sure about how to deal with listeners when they are part of |
@tmorehouse data attributes are in the whitelist (it is mentioned at the very beginning of the RFC) |
@posva re custom events, there still can be confusion between custom component events and native events that use the same name (i.e. |
Why is How does this work with multiple root nodes? Do the passed attributes apply to all root nodes or will the fallthrough be disabled for such components? I like having to define Why does it need to be made complicated and confusing by only having a few attributes pass through? Everything should be inherited or nothing should be inherited otherwise it's confusing as to why some things work and others don't. The users of a component should be able to add whatever attributes they want without having to worry about the component author passing them through to the child components. Components should only have control over attributes/events they have explicitly defined in props/emits IMO unless they set
So make it affect those attributes. If the component author specifies
Have event listeners inherited by default so we can get rid of
Treat class and style like any other attribute and treat v-on listeners as they currently are. In short, I feel like components should have to explicitly define what they can control and everything else should be passed down to the child components. Component authors should be given more control to declare exactly what their component needs to access. |
Closing - superseded by #154 |
This proposal is a replacement of #92.
Implicit fallthrough now by default only applies for a whitelist of attributes (
class
,style
, event listeners, a11y attributes, and data attributes).Implicit fallthrough now works consistently for both stateful and functional components (as long as the component has a single root node).
this.$attrs
now contains everything passed to the component minus those explicitly declared as props, includingclass
,style
, and listeners. (this.$listeners
is removed)The main reason for the revision is the conflict between Optional Props Declaration and the implicit fallthrough behavior. See detailed explanation in the Motivation section.
Full Proposal, Rendered