Heim  >  Fragen und Antworten  >  Hauptteil

Der neu ausgedrückte Titel lautet: v-if basierend auf DOM-Updates

Ich habe einige Elemente mit v-for gerendert Jedes Element enthält Text und Schaltflächen Ich muss die Schaltfläche nur anzeigen, wenn der Text die Höhe des Div überschreitet

<div v-for="el in elements" :key="el.id">
    <span>{{ el.text }}</span>
    <button>Click me</button>
</div>

Die offensichtliche Lösung ist die Verwendung von v-if, aber auf welcher Grundlage sollte ich dies basieren? Ich muss die Höhe des Textes berechnen und entscheiden, ob die Schaltfläche angezeigt werden soll oder nicht Daher muss ich Refs verwenden, um auf die Divs zu verweisen, und eine Funktion, um zu bestimmen, ob Folgendes angezeigt werden soll:

<template>
    <button @click="addDiv"> 点击添加div </button>
    <div v-for="(el, index) in elements" :key="el.id">
        <span ref="items">{{ el.text }}</span>
        <button v-if="showButton(index)">Click me</button>
    </div>
</template>

<script setup lang="ts">
//imports
const elements = ref([]);
const addDiv = function() { 
    elements.value.push({ text: "测试", id: Date.now() })
}
const items = ref();
const showButton = function (index) {
    const item = items.value[index] as HTMLElement;
    return item.scrollHeight > item.offsetHeight
}
</script>

Aber ich habe festgestellt, dass das Problem itemsnicht mit dem DOM synchronisiert ist. Das DOM wird also offensichtlich asynchron aktualisiert und deshalb sind meine Daten etwas spät Also habe ich beschlossen, nextTick() in meine showButton-Funktion einzufügen, aber es begann Promise zurückzugeben, was dazu führte, dass das V-If immer wahr war

<template>
    <button @click="addDiv"> 点击添加div </button>
    <div v-for="(el, index) in elements" :key="el.id">
        <span ref="items">{{ el.text }}</span>
        <button v-if="showButton(index)">Click me</button>
    </div>
</template>

<script setup lang="ts">
//imports
const elements = ref([]);
const addDiv = function() { 
    elements.value.push({ text: "测试", id: Date.now() })
}
const items = ref();
const showButton = function (index) {
    nextTick(() => {
        const item = items.value[index] as HTMLElement;
        return item.scrollHeight > item.offsetHeight
    })
}
</script>

Gibt es also eine Möglichkeit, meine Schaltflächen speziell für jedes Element anzuzeigen oder auszublenden?

P粉163951336P粉163951336405 Tage vor495

Antworte allen(1)Ich werde antworten

  • P粉187677012

    P粉1876770122023-09-11 00:40:21

    我使用Vue中的watchers来完成了这个操作,希望能对你有所帮助!

    <template>
      <button @click="addDiv">点击添加div</button>
      <div
        v-for="el in elements"
        :key="el.id"
      >
        <span ref="items">{{ el.text }}</span>
        <button v-if="el.showButton">点击我</button>
      </div>
    </template>

    而且脚本部分,我已经更新了输入部分:

    <script setup lang="ts">
      //imports
      import { ref, watch } from 'vue';
    
      const elements = ref<Array<any>>([]);
      const items = ref<Array<HTMLElement>>([]);
    
      const addDiv = function () {
        elements.value.push({ text: '测试', id: Date.now(), showButton: false });
      };
    
      watch(items.value, (newItems) => {
        console.log('items changed');
        let cpt = 0;
    
        // you can do it with a for loop too
        newItems.forEach((item) => {
          if (item.scrollHeight > item.offsetHeight) {
            console.log('overflow -> show button');
            elements.value[cpt].showButton = true;
          }
          cpt++;
        });
      });
    </script>

    Antwort
    0
  • StornierenAntwort