Vue.js-Ref innerhalb der v-for-Schleife

Lesezeit: 6 Minuten

Benutzeravatar von Lev Chruschtschow
Lew Chruschtschow

Ich habe versucht, Komponenten im Inneren zu verwenden v-for Schleife und initieren Sie die ref um in Zukunft auf einige Methoden dieser Eltern zugreifen zu können. Hier ein vereinfachter Code meines Falls:

<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>

Und ListItem Komponente:

<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>

Es werden nur ein paar Listenelemente gerendert und eines davon nach anderthalb Sekunden hervorgehoben. Aber ich habe einen Fehler: Uncaught TypeError: _this.$refs.item2.highlight is not a function

Nach der Debug-Sitzung habe ich eine interessante Tatsache gefunden: Refs sind im Inneren definiert v-for Schleife sind keine Komponenten, sondern die Arrays mit einer Komponente.
Was ist die Logik, was ist der f-Wrapper? Kennt jemand diesen Fall? Kann jemand dieses Verhalten erklären?
Der oben dargestellte Code funktioniert gut mit setTimeout(() => this.$refs.item2[0].highlight(), 1500);

Muss ich immer passieren [0]? Gibt es einen besseren Weg? Hilfe bitte.

  • When ref is used together with v-for, the ref you get will be an array containing the child components mirroring the data source. – ist es das?

    – raina77ow

    29. August 2018 um 21:43 Uhr

Wenn Sie Refs mit v-for verwenden, werden die Komponenten-/DOM-Knoten als Array direkt im Variablennamen gespeichert, sodass Sie keine Indexnummer im Ref-Namen verwenden müssen. Sie können also Folgendes tun:

<list-item
  v-for="item in items" 
  :key="item.id" 
  :value="item.text" 
  ref="items"
/>

Und verwenden Sie die Refs in Ihrer Komponente wie folgt:

this.$refs.items[index]

Beachten Sie auch, dass die Refs möglicherweise nicht in Ordnung sind und auf andere Weise gehandhabt werden müssten, was ein völlig anderes Problem darstellt. Das kannst du hier verfolgen: https://github.com/vuejs/vue/issues/4952

  • In der Tat brauchen Sie keinen Index in v-for Schleife für ref.

    – Alexander Kim

    29. Juli 2019 um 18:37 Uhr

  • Wie verwende ich das mit der Kompositions-API?

    – ausbessern3

    23. Februar 2021 um 10:02 Uhr


  • Beachten Sie, dass dies in Vue 3 nicht funktioniert

    – Roll

    22. Oktober 2021 um 12:24 Uhr

  • Was wäre, wenn Sie mehrere Elemente innerhalb des v-for hätten, einschließlich einer Eingabe? und Sie möchten die Eingabe fokussieren. Wie würden Sie auf die spezifische Eingabe innerhalb dieser Ref-Lösung zugreifen?

    – Ihr IVDLO

    5. November 2021 um 14:14 Uhr


  • Bearbeiten Ich habe herausgefunden, wie Sie .children hinzufügen können[index] bis zum Ende, um durch die Elemente innerhalb des v-for zu navigieren

    – Ihr IVDLO

    5. November 2021 um 14:35 Uhr

Benutzeravatar von Syed
Syd

Für Vue 3-Benutzer:

In Vue 3 wird bei einer solchen Verwendung nicht mehr automatisch ein Array in erstellt $refs. Um mehrere Verweise aus einer einzelnen Bindung abzurufen, binden Sie ref zu einer Funktion, die mehr Flexibilität bietet (dies ist ein neues Feature):

HTML

<div v-for="item in list" :ref="setItemRef"></div>

Mit Options-API:

export default {
  data() {
    return {
      itemRefs: []
    }
  },
  methods: {
    setItemRef(el) {
      if (el) {
        this.itemRefs.push(el)
      }
    }
  },
  beforeUpdate() {
    this.itemRefs = []
  },
  updated() {
    console.log(this.itemRefs)
  }
}

Mit Kompositions-API:

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
    }
  }
}

Hier ist der Doc-Link: https://v3-migration.vuejs.org/breaking-changes/array-refs.html

  • Bitte fügen Sie eine Zeile hinzu, wie die Referenz verwendet werden soll, sagen Sie zum Beispiel, sich auf ein Element zu konzentrieren und auf seine Referenz zu verweisen

    – Joel G Mathew

    28. September 2021 um 19:31 Uhr

  • @JoelGMathew Es ist eine sehr spezifische Anfrage, wenn Sie Hilfe benötigen, pingen Sie mich bitte über Skype an: syed_haroon

    – Syd

    29. September 2021 um 4:20 Uhr

  • Laut den neuen Dokumenten ist diese Funktion ab 3.2.25 in vue 3 wieder verfügbar staging.vuejs.org/guide/essentials/…

    – Santiago Arizti

    2. Februar um 0:47

Ich habe versucht, Refs innerhalb von v-for zu handhaben, indem ich den Index von der Methode übergebe:

<div v-for="(item, index) in items" @click="toggle(index)">
  <p ref="someRef"></p>
</div>

toggle(index) {
  this.refs['someRef'][index].toggle();
}

Aber in Wirklichkeit wurden die falschen Elemente umgeschaltet, da die Indizes von Refs nicht geordnet sind.

Also habe ich den ref-Elementen ein Datenattribut hinzugefügt:

<div v-for="(item, index) in items" @click="toggle(index)">
  <p ref="someRef" :data-key="index"></p>
</div>

Jetzt hat jede Referenz ihren spezifischen Datenschlüssel. Und kann so umgeschaltet werden:

toggle(index) {
  const dropdown = this.$refs['someRef'].find(
        el => el.$attrs['data-key'] === index
    );
  dropdown.toggle();
}

Ich hatte vor dem gleichen Problem gestanden.

Wie sobolevon erwähnt, der Rückgabewert von $refs.{ref name} ist ein Array in v-for refs, also ist meine Lösung zu berücksichtigen $refs.{ref name} ist ein Array mit nur einem Element standardmäßig und schreiben $refs.{ref name}[0].methodToCall().

Und es funktioniert für meinen Fall.

Vissies Benutzeravatar
Vissi

Für alle, die Vue 3 mit Typescript und diesem (vuejs/core#5525) Problem noch offen. Basierend auf den anderen Antworten können Sie Folgendes tun:

Aktualisieren: vuejs/core#5525 scheint behoben zu sein, daher ist eine andere Lösung möglicherweise besser.

<div
   v-for="item in items"
   :ref="addRef"
   ...
</div>

...

function addRef(el: unknown) {
  if (el instanceof Element) {
    participantRefs.value.push(el);
  }
}

  • Ich habe dieses Problem beobachtet und es sieht so aus, als ob es kürzlich behoben wurde 👍🏼

    – Kaleb Waldner

    28. Mai um 20:34 Uhr

Benutzeravatar von Yitz
Yitz

Ich habe das Bestellproblem gelöst, indem ich eine dynamische Referenz verwendet habe: :ref="'myRef' + index".

Wenn Sie dies tun, erstellt Vue für jedes Element im v-for ein neues Array, dessen einziges Element immer die gewünschte Referenz ist. Sie können dann mit darauf zugreifen this.$refs['myRef' + index][0].

(Dies funktioniert nicht in Vue 3.)

  • Ich habe dieses Problem beobachtet und es sieht so aus, als ob es kürzlich behoben wurde 👍🏼

    – Kaleb Waldner

    28. Mai um 20:34 Uhr

Benutzeravatar von Prajeesh KP
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>

  • Hallo und willkommen bei StackOverflow! Bitte geben Sie weitere Details dazu an, was Ihr Code tut und warum er die Frage beantwortet.

    – Ad5001

    30. Juli 2021 um 13:21 Uhr

1434510cookie-checkVue.js-Ref innerhalb der v-for-Schleife

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy