英文:
v-if based on result of DOM updating
问题
Sure, here's the translated code snippet:
我有一些使用v-for渲染的元素
每个元素都包括文本和按钮
只有当文本溢出div的高度时,我才需要显示按钮
<div v-for="el in elements" :key="el.id">
<span>{{ el.text }}</span>
<button>点击我</button>
</div>
显而易见的解决方案是使用v-if,但我应该基于什么呢?
我需要计算文本的高度,然后决定是否显示按钮
因此,我需要为div添加引用并编写一个函数来确定是否显示按钮:
<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)">点击我</button>
</div>
</template>
<script setup lang="ts">
// 导入
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)">点击我</button>
</div>
</template>
<script setup lang="ts">
// 导入
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>
那么,有没有办法为每个元素单独显示或隐藏我的按钮?
I've provided the translated code snippet as requested. If you have any further questions or need assistance with specific parts of the code, feel free to ask.
英文:
I have elements that are rendered using v-for
Each element consist of text and button
I need to show a button only if text is overflow div's height
<div v-for="el in elements" :key="el.id">
<span>{{ el.text }}</span>
<button>Click me</button>
</div>
Evident solution is use v-if, but what should I based on?
I need to calculate height of text and decide to show button or not
So I need refs for divs and function to determine show or not:
<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>
But I found the issue is that items
are not synchronous with DOM. So it is clear why, DOM is updated asynchronously and that's why my data is a little bit late
So I decided to add nextTick()
in my showButton function, but it started to return Promise, which leads to v-if always 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>
So is there any way to show or not my button for each element specifically?
答案1
得分: 1
I did it using the watchers in Vue, I hope it will help you!
<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>
and the script, I've updated the typing part:
<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>
英文:
I did it using the watchers in Vue, I hope it will help you !
<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>
and the script, I've updated the typing part:
<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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论