ref doesn't work properly with v-for together
Jinjiang opened this issue · 8 comments
Version
3.0.0-beta.10
Reproduction link
https://codesandbox.io/s/goofy-yalow-d0x6e?file=/src/App.vue
Steps to reproduce
<template>
<span v-for="n in 10" ref="x">{{ n }}</span>
</template>
<script>
export default {
mounted() {
console.log(this.$refs.x);
}
}
</script>
What is expected?
print an array of all spans
What is actually happening?
the last span
When used on elements/components with
v-for
, the registered reference will be an Array containing DOM nodes or component instances.
Vue 3 no longer has special behavior for v-for
refs: https://composition-api.vuejs.org/api.html#template-refs
Actually, we may need to detect non composition api usage for backwards compat. Or we need an RFC to officially deprecate this (I never considered it good practice anyway, and it creates a TON of complexity when used inside nested v-for
s.)
Gotcha. My quick idea is introducing another refs="x"
for v-for
which equals to :ref="el => $refs.x[i] = el
. So it’s easy to code-mod and deprecate further I guess. Maybe will propose something like that later to RFCs. Thanks.
It's worth noting that the current v3 docs do explicitly note support for v-for
with refs
:
When ref is used together with v-for, the ref you get will be an array containing the child components mirroring the data source.
https://v3.vuejs.org/guide/component-template-refs.html
If this should be changed to reflect the current status I'm happy to PR.
Is there any migration strategy for about this?
Actually, we may need to detect non composition api usage for backwards compat. Or we need an RFC to officially deprecate this (I never considered it good practice anyway, and it creates a TON of complexity when used inside nested v-fors.)
@yyx990803 We actually can do the same thing we recommend for the composition with the options API:
Example: https://jsfiddle.net/Linusborg/xjcbyw2f/1/
This should in theory also allow people to come up with a strategy for nested v-for situations (which, I agree, are a complexity nightmare)
@syuilo That should work as a migration strategy I think.
@vuejs/docs Can we add this example to the migration guide for Options-API users?
Im not sure to understand why you say it can create complexity. Isn't the goal of this feature to be an alternative to document.getElementById and document.getElementByClassName without breaking the component logic (document.getElementById can access DOM on other components but ref cant)? Isn't :ref="el => listElements.push(el)"
less readable then :ref=listElements"
?
I just want to understand why this decision happened, because I just can't see a good reason why it should have