Open jods4 opened 4 years ago
For reference, here's a working demo: https://codesandbox.io/s/laughing-mountain-d9z9l?file=/index.html
Thank you for this issue.
First, Vue.js official documentation states that,
when only the default slot is provided content, the component’s tags can be used as the slot’s template. This allows us to use v-slot directly on the component
An example this in the valid-v-slot
rule documentation is:
The directive is a named slot and is on a custom element directly. E.g.
<my-component v-slot:foo></my-component>
As I can see, the rule is working correctly, but as you said, the shorthand syntax seems to work for more than the default
slot.
Hmm... I think we need to make sure that it is the intended behavior.
First, Vue.js official documentation states that,
when only the default slot is provided content, the component’s tags can be used as the slot’s template. This allows us to use v-slot directly on the component
I read the whole paragraph and unless I made a logic mistake it doesn't say you can't use the component tag for a non-default slot when only it's the only content. Then again it doesn't so you can either so: 😕
Also it's the Vue 2 documentation and slots have changed quite a bit, so I am not sure if it's 100% reliable for Vue 3.
An example this in the valid-v-slot rule documentation is:
You are right, sorry. I always use the shorthand #foo
and got confused.
Hmm... I think we need to make sure that it is the intended behavior.
Thank you! I'm watching this issue 👀
I forgot to tell you one. Your template will probably work with Vue.js 2.
There is also a use case here that #default
is perfectly valid and works correctly to make the default slot behave as a scoped slot rather than a non-scoped slot:
<my-component #default>
<!-- lazy default slot content - only evaluated if my-component actually renders the default slot -->
Default Slot Content
</my-component>
The above is functionally different from:
<my-component>
<!-- eager default slot content - evaluated even if my-component does not render the default slot -->
Default Slot Content
</my-component>
To re-iterate the above comments. This is valid and shouldn't emit a warning when vue/valid-v-slot
is on.
There is also a use case here that
#default
is perfectly valid and works correctly to make the default slot behave as a scoped slot rather than a non-scoped slot:<my-component #default> <!-- lazy default slot content - only evaluated if my-component actually renders the default slot --> Default Slot Content </my-component>
The above is functionally different from:
<my-component> <!-- eager default slot content - evaluated even if my-component does not render the default slot --> Default Slot Content </my-component>
@ascott18 is this documented somewhere?
Intuitively, it feels very surprising to the point I think it may be a bug.
When a component has contents, I'd expected to work as if it had #default
... by default.
@ascott18 is this documented somewhere? Intuitively, it feels very surprising to the point I think it may be a bug. When a component has contents, I'd expected to work as if it had
#default
... by default.
@jods4 Yes - its defined in the RFC that introduced v-slot
: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0001-new-slot-syntax.md#introducing-a-new-directive-v-slot
v-slot can be used directly on a component, without an argument, to indicate that the component's default slot is a scoped slot, and that props passed to the default slot should be available as the variable declared in its attribute value:
In my example, #default
is just an alternate form of v-slot
. v-slot
== v-slot:default
== #default
. You can't take this to the furthest extreme (a single #
) for obvious reasons.
See template compilation result - the first 3 are identical, the last one is not: https://template-explorer.vuejs.org/#%3Cdiv%3E%0A%20%20%3Cmy-component%20v-slot%3E%0A%20%20%20%20lazy%20content%0A%20%20%3C%2Fmy-component%3E%0A%0A%20%20%3Cmy-component%20v-slot%3Adefault%3E%0A%20%20%20%20lazy%20content%0A%20%20%3C%2Fmy-component%3E%0A%20%20%0A%20%20%3Cmy-component%20%23default%3E%0A%20%20%20%20lazy%20content%0A%20%20%3C%2Fmy-component%3E%0A%20%20%0A%20%20%3Cmy-component%3E%0A%20%20%20%20eager%20content%0A%20%20%3C%2Fmy-component%3E%0A%3C%2Fdiv%3E
@sirlancelot 's example is essentially the same thing - just a different syntax.
@ascott18
This is documentation that v-slot
by itself is v-slot:default
, which I would expect.
The part that is nagging me is what happens of the content of a custom element without v-slot.
Intuitively I would expect it to be either dropped silently (no evaluation) or better, to be the same as v-slot:default
.
Is there any documentation that describes what you called "eager default slot" and how it differs in behavior from what you called "lazy default slot"?
@jods4 The contents of scoped slots in a compiled template are placed in the body of a closure. This allows the slot content to be rendered independent from the template root where the slot contents were defined. This also allows the slot contents to be conditionally rendered into a VNode tree only if the component actually renders the slot.
The contents of non-scoped slots are rendered into a VNode tree whenever the component where the slot contents were defined is rendered, regardless of whether that slot is actually being rendered by the parent component or not.
In Vue 3, all slots will be treated like scoped slots are in Vue 2 - there won't distinction anymore between scoped (lazy) and unscoped (eager) slots.
You can see all of this quite clearly if you look at the template compiler output I linked above. Here's a new link with one more example using the legacy slot
attribute (which creates an unscoped slot):
@ascott18 great, so in Vue 3 using v-slot
or not compiles to the same thing, which is what I expected.
Your link is for Vue 2 (which is not compiling both cases to the same code); for reference if anyone wants to check this is the Vue 3 version, where all cases compile to the same:
https://vue-next-template-explorer.netlify.app/#%7B%22src%22%3A%22%3Cdiv%3E%5Cr%5Cn%20%20%3Cmy-component%20v-slot%3E%5Cr%5Cn%20%20%20%20lazy%20content%20%231%5Cr%5Cn%20%20%3C%2Fmy-component%3E%5Cr%5Cn%5Cr%5Cn%20%20%3Cmy-component%20v-slot%3Adefault%3E%5Cr%5Cn%20%20%20%20lazy%20content%20%232%5Cr%5Cn%20%20%3C%2Fmy-component%3E%5Cr%5Cn%20%20%5Cr%5Cn%20%20%3Cmy-component%20%23default%3E%5Cr%5Cn%20%20%20%20lazy%20content%20%233%5Cr%5Cn%20%20%3C%2Fmy-component%3E%5Cr%5Cn%20%20%5Cr%5Cn%20%20%3Cmy-component%3E%5Cr%5Cn%20%20%20%20eager%20content%20%234%5Cr%5Cn%20%20%3C%2Fmy-component%3E%5Cr%5Cn%20%20%5Cr%5Cn%20%20%3Cmy-component%3E%5Cr%5Cn%20%20%20%20%3Ctemplate%20slot%3D%5C%22default%5C%22%3E%20%5Cr%5Cn%20%20%20%20%5Cteager%20content%20%235%5Cr%5Cn%20%20%20%20%3C%2Ftemplate%3E%5Cr%5Cn%20%20%3C%2Fmy-component%3E%5Cr%5Cn%3C%2Fdiv%3E%22%2C%22options%22%3A%7B%22mode%22%3A%22module%22%2C%22prefixIdentifiers%22%3Afalse%2C%22optimizeImports%22%3Afalse%2C%22hoistStatic%22%3Afalse%2C%22cacheHandlers%22%3Afalse%2C%22scopeId%22%3Anull%2C%22ssrCssVars%22%3A%22%7B%20color%20%7D%22%2C%22bindingMetadata%22%3A%7B%22TestComponent%22%3A%22setup%22%2C%22foo%22%3A%22setup%22%2C%22bar%22%3A%22props%22%7D%2C%22optimizeBindings%22%3Atrue%7D%7D
Vuetify's v-data-table uses v-slot:item.column="" which valid-v-slot complains about. See example code here: https://vuetifyjs.com/en/components/data-tables/#slots
@ricochet1k already reported in https://github.com/vuejs/eslint-plugin-vue/issues/1165
This also false-positives on:
<template #head(foo.bar)="data">
With bootstrap-vue b-table
s, where it's not easy to workaround other than ignoring the lint, because foo.bar
and foo.baz
might both be keys in the table fields.
This part of the valid-v-slot rule that is in 7.0.0-beta.8 is triggered in my code: https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/valid-v-slot.js#L210
Basically, a named slot on anything but a template triggers it, for example:
What it would like me to do is:
I don't quite understand why this rule is in place, as that first code snippet works for me (at least in Vue 3, no idea if it works in Vue 2 as well) and the second one is more verbose with no (visible?) benefit.
Looking at the rule documentation, this case is not listed in text nor given as a code example: https://eslint.vuejs.org/rules/valid-v-slot.html
Could you provide guidance here? What's the motivation behind the rule?