Compiler should warn about duplicate/conditional slots
Version
3.2.31
Reproduction link
vue-next-template-explorer.netlify.app
Steps to reproduce
Look at the AST for the SFC. In the dev console, you can see the component has only one child.
The workaround example (from below) has the part that is missing. branches
is present for conditional rendering
What is expected?
Both named-slots are registered in the AST.
What is actually happening?
Only one of the conditional templates with named slots is registered in the AST. The second is not.
Reference: https://github.com/johnsoncodehk/volar/issues/1150
Workaround: not put a condition on template of named slot but instead make the content conditional
SFC that generates bad AST
<script
setup
lang="ts"
>
import { ref } from 'vue';
import ComponentWithSlots from '@/src/foobar';
const aVariableThatExists = ref(true);
</script>
<template>
<ComponentWithSlots>
<template
#content
v-if="aVariableThatExists"
>
<div>{{ aVariableThatExists }}</div>
</template>
<template
#content
v-else
>
<div>{{ thisVariableDoesNotExist }}</div>
<div>{{ thisShouldBeUnderlinedInRed }}</div>
</template>
</ComponentWithSlots>
</template>
Workaround SFC
Move the conditional logic into the children of a single slotted template. Define an extra set of template tags that the conditional logic can live on:
<script
setup
lang="ts"
>
import { ref } from 'vue';
import ComponentWithSlots from '@/src/foobar';
const aVariableThatExists = ref(true);
</script>
<template>
<ComponentWithSlots>
<template
#content
>
<template v-if="aVariableThatExists">
<div>{{ aVariableThatExists }}</div>
</template>
<template v-else>
<div>{{ thisVariableDoesNotExist }}</div>
</template>
</template>
</ComponentWithSlots>
</template>
This issue was originally created as a Volar issue at which point we determined it is a legitimate Vue bug.
I think we had an issue about that before and the consensus was that v-if on slot templates isn't allowed, and the "workaround" shown here is the intended way to use conditional slots,
Provided my memory is correct, we likely should document this better, and have the compiler throw an error in this case.
I think we had an issue about that before and the consensus was that v-if on slot templates isn't allowed, and the "workaround" shown here is the intended way to use conditional slots
Sorry to ping @LinusBorg, but I feel like a lot of vue users are using this pattern extensively. If I follow you correctly, you are saying that this is not supported anymore ? It feels like a big breaking change, see https://github.com/vuejs/core/issues/6651 for instance.
Rendering slots conditionally is the only way to work reliably with existence check provided by $slots.xxx The workaround does not help with this.
Just wondering if this topic should be raised again and bumped up, since it seems like a legit issue.
In our codebase, Vue language tool is not functioning properly and eslint autofixed is removing some imports because it doesn't know about all AST Nodes :(