搜尋

首頁  >  問答  >  主體

重新表達的標題為:v-if based on DOM updates

我有一些使用v-for渲染的元素 每個元素包含文字和按鈕 只有當文字溢出div的高度時,我才需要顯示按鈕

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

明顯的解決方案是使用v-if,但我應該基於什麼來判斷? 我需要計算文字的高度,並決定是否顯示按鈕 因此,我需要使用refs來引用divs,並使用函數來確定是否顯示:

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

但我發現問題是items與DOM不同步。所以很明顯,DOM是非同步更新的,這就是為什麼我的數據有點晚 所以我決定在我的showButton函數中加入nextTick(),但它開始回傳Promise,這導致v-if始終為true

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

那麼有沒有辦法針對每個元素特定地顯示或隱藏我的按鈕呢?

P粉163951336P粉163951336564 天前581

全部回覆(1)我來回復

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

    回覆
    0
  • 取消回覆