vue.js 基于DOM更新结果的v-if

avkwfej4  于 2023-05-29  发布在  Vue.js
关注(0)|答案(1)|浏览(141)

我有使用v-for渲染的元素每个元素都由文本和按钮组成,只有当文本溢出div的高度时,我才需要显示按钮

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

明显的解决方案是使用v-if,但我应该基于什么?我需要计算文本的高度,并决定是否显示按钮,所以我需要div和函数的引用来确定是否显示:

<template>
    <button @click="addDiv"> Click to add 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: "Test", 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"> Click to add 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: "Test", id: Date.now() })
}
const items = ref();
const showButton = function (index) {
    nextTick(() => {
        const item = items.value[index] as HTMLElement;
        return item.scrollHeight > item.offsetHeight
    })
}
</script>

那么,有没有什么方法可以显示或不显示每个元素的按钮呢?

eimct9ow

eimct9ow1#

我在Vue中使用了watchers,希望对你有帮助!

<template>
  <button @click="addDiv">Click to add div</button>
  <div
    v-for="el in elements"
    :key="el.id"
  >
    <span ref="items">{{ el.text }}</span>
    <button v-if="el.showButton">Click me</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: 'Test', 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>

相关问题