Maison  >  Questions et réponses  >  le corps du texte

Le titre réexprimé est : v-if basé sur les mises à jour du DOM

J'ai rendu certains éléments en utilisant v-for Chaque élément contient du texte et des boutons Je dois afficher le bouton uniquement lorsque le texte dépasse la hauteur du div

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

La solution évidente est d'utiliser v-if, mais sur quelle base dois-je baser cela ? Je dois calculer la hauteur du texte et décider d'afficher ou non le bouton Par conséquent, je dois utiliser des références pour référencer les divs et une fonction pour déterminer s'il faut afficher :

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

Mais j'ai trouvé que le problème n'est itemspas synchronisé avec le DOM. Alors évidemment, le DOM est mis à jour de manière asynchrone et c'est pour ça que mes données arrivent un peu en retard J'ai donc décidé d'ajouter nextTick() dans ma fonction showButton, mais elle a commencé à renvoyer Promise, ce qui a fait que le v-if était toujours vrai

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

Alors, existe-t-il un moyen d'afficher ou de masquer mes boutons spécifiquement pour chaque élément ?

P粉163951336P粉163951336405 Il y a quelques jours493

répondre à tous(1)je répondrai

  • P粉187677012

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

    J'ai utilisé watchers dans Vue pour réaliser cette opération, j'espère que cela pourra vous être utile !

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

    Et la partie script, j'ai mis à jour la partie saisie :

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

    répondre
    0
  • Annulerrépondre