core
core copied to clipboard
sometimes template can not apply key by v-for
Link to minimal reproduction
https://stackblitz.com/edit/vue3-forwarding-slots-qmswhv?file=src%2FApp.vue,src%2Fcomponents%2FComponentA.vue
Steps to reproduce
None.
What is expected?
Works.
What is actually happening?
It report error.

System Info
System:
OS: macOS 12.3.1
CPU: (10) arm64 Apple M1 Max
Memory: 2.97 GB / 32.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 16.15.0 - /opt/homebrew/opt/node@16/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 8.5.5 - /opt/homebrew/opt/node@16/bin/npm
Browsers:
Chrome: 101.0.4951.64
Firefox: 100.0.1
Safari: 15.4
Any additional comments?
See https://github.com/vuejs/core/discussions/5962.
Moving the :key binding from <template> to <slot> resolves the issue:
<van-loading>
<template v-for="(_, slot) of $slots" v-slot:[slot]="scope">
👇
<slot :name="slot" v-bind="scope" :key="slot" />
</template>
</van-loading>
Moving the
:keybinding from<template>to<slot>resolves the issue:<van-loading> <template v-for="(_, slot) of $slots" v-slot:[slot]="scope"> 👇 <slot :name="slot" v-bind="scope" :key="slot" /> </template> </van-loading>
Thanks for your quick reply.
Please look at componentB in the copied link, is this another problem?
It seems that adding key can also be solved, but there is no v-for here.
Your usage in that blitz doesn't make sense to me. To forward the default slot, just use <slot/>:
<template>
<van-loading v-bind="$attrs">
<slot />
</van-loading>
</template>
Thanks for your help, adding the key to the slot solved my problem, there's only one lint error left that confuses me. https://github.com/vuejs/eslint-plugin-vue/issues/1900 I disabled the rule to make it works.
Not sure about the key issue. I'm wondering if <template>'s key is supposed to be automatically applied to <slot> children. Nothing in the docs suggests the key should be manually/explicitly moved to the children, so it might be a Vue bug after all (not a linter bug). 🤔
Not sure about the
keyissue. I'm wondering if<template>'skeyis supposed to be automatically applied to<slot>children. Nothing in the docs suggests thekeyshould be manually/explicitly moved to the children, so it might be a Vue bug after all (not a linter bug). 🤔
So do you think this needs to be fixed in vue? Alternatively, others who got this error should also take the solution you gave me as the final solution?
So do you think this needs to be fixed in
vue?
Yes, I think so. But the template in the original repro is invalid IMO (see comment). I recommend creating a new issue with valid markup that generates the error.
Alternatively, others who got this error should also take the solution you gave me as the final solution?
Assuming the key issue is indeed a Vue bug, adding the key binding to the <slot> (and disabling the linter warning for those lines only) is a reasonable workaround for the time being.
Yes, I think so. But the template in the original repro is invalid IMO (see comment). I recommend creating a new issue with valid markup that generates the error.
I've updated it https://stackblitz.com/edit/vue3-forwarding-slots-qmswhv?file=src%2FApp.vue,src%2Fcomponents%2FComponentA.vue
any update on this ?
I have this code part of a Vue 3 migration :
<template>
<v-card
rounded="0"
:loading="loading"
>
<v-card-title>
Exécutions
</v-card-title>
<v-list class="py-0">
<template v-if="runs">
<template v-for="run in runs.results">
<v-divider :key="run._id + '-divider'" />
<run-list-item
:key="run._id + '-item'"
:run="run"
:link="true"
:can-exec="canExec"
/>
</template>
</template>
</v-list>
</v-card>
</template>
indeed, eslint-plugin-vue triggers : <template v-for> key should be placed on the <template> tag
but when I change it, it triggers again : '<template v-for>' cannot be keyed. Place the key on real elements instead
I'm perplex
@EDM115 That's not related to this issue.
Your problem is that your eslint config has two rules active that are incompatible.
The first error is from the Vue 3 rule: https://eslint.vuejs.org/rules/no-v-for-template-key-on-child.html#vue-no-v-for-template-key-on-child
The second error is from the Vue 2 rule: https://eslint.vuejs.org/rules/no-v-for-template-key.html
So the solution would be to disable one of them - likely the second one as you are on Vue 3 now.
indeed, there was an oversight in my eslint config
thanks, this was driving me insane :)