基于DOM更新结果的v-if。

huangapple go评论65阅读模式
英文:

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

&lt;div v-for=&quot;el in elements&quot; :key=&quot;el.id&quot;&gt;
&lt;span&gt;{{ el.text }}&lt;/span&gt;
&lt;button&gt;Click me&lt;/button&gt;
&lt;/div&gt;

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:

&lt;template&gt;
&lt;button @click=&quot;addDiv&quot;&gt; Click to add div &lt;/button&gt;
&lt;div v-for=&quot;(el, index) in elements&quot; :key=&quot;el.id&quot;&gt;
&lt;span ref=&quot;items&quot;&gt;{{ el.text }}&lt;/span&gt;
&lt;button v-if=&quot;showButton(index)&quot;&gt;Click me&lt;/button&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;script setup lang=&quot;ts&quot;&gt;
//imports
const elements = ref([]);
const addDiv = function() { 
elements.value.push({ text: &quot;Test&quot;, id: Date.now() })
}
const items = ref();
const showButton = function (index) {
const item = items.value[index] as HTMLElement;
return item.scrollHeight &gt; item.offsetHeight
}
&lt;/script&gt;

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

&lt;template&gt;
&lt;button @click=&quot;addDiv&quot;&gt; Click to add div &lt;/button&gt;
&lt;div v-for=&quot;(el, index) in elements&quot; :key=&quot;el.id&quot;&gt;
&lt;span ref=&quot;items&quot;&gt;{{ el.text }}&lt;/span&gt;
&lt;button v-if=&quot;showButton(index)&quot;&gt;Click me&lt;/button&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;script setup lang=&quot;ts&quot;&gt;
//imports
const elements = ref([]);
const addDiv = function() { 
elements.value.push({ text: &quot;Test&quot;, id: Date.now() })
}
const items = ref();
const showButton = function (index) {
nextTick(() =&gt; {
const item = items.value[index] as HTMLElement;
return item.scrollHeight &gt; item.offsetHeight
})
}
&lt;/script&gt;

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 !

&lt;template&gt;
&lt;button @click=&quot;addDiv&quot;&gt;Click to add div&lt;/button&gt;
&lt;div
v-for=&quot;el in elements&quot;
:key=&quot;el.id&quot;
&gt;
&lt;span ref=&quot;items&quot;&gt;{{ el.text }}&lt;/span&gt;
&lt;button v-if=&quot;el.showButton&quot;&gt;Click me&lt;/button&gt;
&lt;/div&gt;
&lt;/template&gt;   

and the script, I've updated the typing part:

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

huangapple
  • 本文由 发表于 2023年5月22日 18:08:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76305088.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定