Lev Jruschov
Traté de usar componentes dentro v-for
bucle e iniciar el ref
para acceder en el futuro a algunos métodos de estos desde los padres. Aquí un código simplificado de mi caso:
<template>
<div class="hello">
{{ msg }}
<ul>
<list-item
v-for="item in items"
:key="item.id"
:value="item.text"
:ref="`item${item.id}`"
/>
</ul>
</div>
</template>
<script>
import ListItem from "./ListItem";
export default {
name: "HelloWorld",
components: {
ListItem
},
data() {
return {
msg: "Welcome to Your Vue.js App",
items: [
{ id: 1, text: "foo" },
{ id: 2, text: "bar" },
{ id: 3, text: "baz" },
{ id: 4, text: "foobar" }
]
};
},
mounted() {
setTimeout(() => this.$refs.item2.highlight(), 1500);
}
};
</script>
Y ListItem
componente:
<template>
<li v-bind:class="{ highlight: isHighlighted }">
{{value}}
</li>
</template>
<script>
export default {
name: "list-item",
props: ["value"],
data() {
return {
isHighlighted: false
};
},
methods: {
highlight() {
this.isHighlighted = !this.isHighlighted;
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.highlight {
color: red;
}
</style>
Solo representa algunos elementos de la lista y resalta uno de ellos después de un segundo y medio. Pero tengo un error: Uncaught TypeError: _this.$refs.item2.highlight is not a function
Después de la sesión de depuración, encontré un hecho interesante: referencias definidas dentro v-for
loop no son componentes sino matrices con un componente.
¿Cuál es la lógica, cuál es el envoltorio f? ¿Alguien conoce este caso? ¿Alguien puede dar la explicación de este comportamiento?
El código presentado arriba funciona bien con setTimeout(() => this.$refs.item2[0].highlight(), 1500);
¿Debo pasar siempre [0]
? ¿Existe una mejor manera? Ayuda por favor.
Cuando se usan referencias con v-for, los nodos del componente/DOM se almacenan como una matriz directamente en el nombre de la variable, por lo que no es necesario usar el número de índice en el nombre de la referencia. Así que puedes hacer esto:
<list-item
v-for="item in items"
:key="item.id"
:value="item.text"
ref="items"
/>
Y use las referencias en su componente de esta manera:
this.$refs.items[index]
También tenga en cuenta que las referencias pueden no estar en orden y deberían manejarse de una manera diferente, lo cual es un problema completamente diferente. Puedes seguir eso aquí: https://github.com/vuejs/vue/issues/4952
-
De hecho, no necesita un índice en
v-for
bucle pararef
.– Alejandro Kim
29 de julio de 2019 a las 18:37
-
¿Cómo uso esto con la API de composición?
– reparando3
23 de febrero de 2021 a las 10:02
-
Tenga en cuenta que esto no funciona en Vue 3
– Roel
22 oct 2021 a las 12:24
-
¿Qué pasaría si tuviera múltiples elementos dentro de v-for, incluida una entrada? y le gustaría enfocar la entrada. ¿Cómo accedería a la entrada específica dentro de esta solución de referencia?
– yourivdloo
5 de noviembre de 2021 a las 14:14
-
Editar Descubrí cómo, puedes agregar .children[index] hasta el final para navegar a través de los elementos dentro de la v-for
– yourivdloo
5 de noviembre de 2021 a las 14:35
Syed
Para usuarios de Vue 3:
En Vue 3, dicho uso ya no creará automáticamente una matriz en $refs
. Para recuperar múltiples referencias de un solo enlace, enlace ref
a una función que proporciona más flexibilidad (esta es una característica nueva):
HTML
<div v-for="item in list" :ref="setItemRef"></div>
Con la API de opciones:
export default {
data() {
return {
itemRefs: []
}
},
methods: {
setItemRef(el) {
if (el) {
this.itemRefs.push(el)
}
}
},
beforeUpdate() {
this.itemRefs = []
},
updated() {
console.log(this.itemRefs)
}
}
Con API de composición:
import { onBeforeUpdate, onUpdated } from 'vue'
export default {
setup() {
let itemRefs = []
const setItemRef = el => {
if (el) {
itemRefs.push(el)
}
}
onBeforeUpdate(() => {
itemRefs = []
})
onUpdated(() => {
console.log(itemRefs)
})
return {
setItemRef
}
}
}
Aquí está el enlace del documento: https://v3-migration.vuejs.org/breaking-changes/array-refs.html
-
Agregue una línea sobre cómo usar la referencia para, por ejemplo, centrarse en un elemento, refiriéndose a su referencia
– Joel G Mathew
28/09/2021 a las 19:31
-
@JoelGMathew es una solicitud muy específica, si necesita ayuda, envíeme un mensaje de Skype:
syed_haroon
– Syed
29 de septiembre de 2021 a las 4:20
-
de acuerdo con los nuevos documentos, esta función vuelve a estar disponible en vue 3 a partir del 3.2.25 staging.vuejs.org/guide/essentials/…
– santiago arizti
2 de febrero a las 0:47
Traté de manejar las referencias dentro de v-for pasando el índice del método:
<div v-for="(item, index) in items" @click="toggle(index)">
<p ref="someRef"></p>
</div>
toggle(index) {
this.refs['someRef'][index].toggle();
}
Pero en realidad estaba alternando los elementos incorrectos ya que los índices de referencias no están ordenados.
Entonces, lo que hice fue agregar un atributo de datos a los elementos de referencia:
<div v-for="(item, index) in items" @click="toggle(index)">
<p ref="someRef" :data-key="index"></p>
</div>
Ahora cada referencia tiene su clave de datos específica. Y se puede alternar así:
toggle(index) {
const dropdown = this.$refs['someRef'].find(
el => el.$attrs['data-key'] === index
);
dropdown.toggle();
}
-
Este método estará frenando en vue3. Así que evito esto si está usando vue3 o posterior: v3.vuejs.org/guide/migration/array-refs.html#frontmatter-title
– rksh
12 de noviembre de 2020 a las 11:56
Me había enfrentado al mismo problema.
Como se mencionó sobolevon, el valor de retorno de $refs.{ref name}
es una matriz en v-for refs, por lo que mi solución es considerar $refs.{ref name}
es una matriz con un solo elemento por defecto, y escribe $refs.{ref name}[0].methodToCall()
.
Y funciona para mi caso.
vissie
Para cualquiera que use Vue 3 con Typescript y esto (vuejs/core#5525) el problema sigue abierto. Según las otras respuestas, puedes hacer algo como esto:
Actualizar: vuejs/core#5525 parece estar arreglado, por lo que una solución diferente puede ser mejor.
<div
v-for="item in items"
:ref="addRef"
...
</div>
...
function addRef(el: unknown) {
if (el instanceof Element) {
participantRefs.value.push(el);
}
}
-
He estado viendo ese problema y parece que se solucionó recientemente 👍🏼
–Caleb Waldner
28 de mayo a las 20:34
Yitz
Resolví el problema del pedido usando una referencia dinámica: :ref="'myRef' + index"
.
Si hace esto, Vue crea una nueva matriz para cada elemento en v-for, cuyo único elemento siempre será la referencia que desea. A continuación, puede acceder a él con this.$refs['myRef' + index][0]
.
(Esto no funcionará en Vue 3).
-
He estado viendo ese problema y parece que se solucionó recientemente 👍🏼
–Caleb Waldner
28 de mayo a las 20:34
Prajeesh KP
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.21/vue.js"></script>
<div
v-for="(item,index) in items"
:key="index">
<q-popup-proxy
ref="qDateProxy">
<q-date
:data-key="index"
v-model="item.date"
@input="CalendarHide(index)"
mask="MM/DD/YYYY"
range>
</q-date>
</q-popup-proxy>
</div>
<script>
CalendarHide (Val) {
this.$refs ['qDateProxy'] [val].hide()
}
</script>
-
¡Hola y bienvenido a StackOverflow! Proporcione más detalles sobre lo que hace su código y por qué responde la pregunta.
– Anuncio5001
30 de julio de 2021 a las 13:21
When ref is used together with v-for, the ref you get will be an array containing the child components mirroring the data source.
– ¿es asi?– lluvia77ow
29 de agosto de 2018 a las 21:43