我正在使用 v-for
循环遍历我的消息。现在,我想要的是检查每条消息的日期,如果日期不同,则显示日期,将其添加到我的数据中,然后继续。这意味着每一天都应该只显示一次。
<template v-for="(message, index) in messages">
<div class="spacer">
<span class="grouped-date" v-if="displayPostDate(message.created_at)">
{{ message.created_at }}
</span>
</div>
</template>
奇怪的是,在我的方法 displayPostDate()
中,我可以检查:
if (!this.datesDone.includes(d)) {}
当我 console.log
它时,它成功运行,但无论我返回什么,Vue 都不会解析正确的数据。
这是displayPostDate()
:
let d = date.substring(0, 10);
if (!this.datesDone.includes(d)) {
console.log('not present');
this.datesDone.push(date.substring(0, 10));
return true;
} else {
console.log('present');
return false;
}
最佳答案
这就是正在发生的事情......
displayPostDate
方法具有更新 react 依赖项的副作用(即,它更新 datesDone[]
),这会导致另一个渲染周期,从而调用该方法再次。
例如,假设您有一个空的 datesDone[]
和 messages[]
中的四个项目,每个项目都有唯一的 created_at
日期。
- 在初始呈现时,
displayPostDate
在其datesDone[]
中找不到任何created_at
日期,因此它将它们附加到数组中。它还返回true
以显示span
。 - Vue 检测到
datesDone[]
的变化——displayPostDate
的依赖项,因此它开始另一个渲染周期。 - 在第二次呈现时,
displayPostDate
找到datesDone[]
中的所有日期,因此datesDone[]
没有发生任何变化。它还返回false
以隐藏span
。由于没有更改依赖项,Vue 不会重新渲染。
这是解决方法...
首先,注意在模板中调用一个方法是inefficient因为每次渲染模板时都会调用它,这可能会发生多次,这反过来又要求该方法是幂等的(并且不更改其 react 性依赖项)以避免渲染循环。
为了解决这个问题,一个更简单的解决方案是预过滤列表,这样它只包含您想要显示的项目(而不是在模板中有条件地呈现)。这有一个额外的好处,可以简化您的模板并消除对 datesDone[]
的需要,假设它除了跟踪重复项没有其他用途。我建议将此列表创建为 computed property这样结果就会被缓存,而不是在另一个渲染周期中不必要地重新计算:
// script
computed: {
uniqueMessages() {
const uniq = this.messages.reduce((c, msg) => {
c[msg.created_at] = c[msg.created_at] || msg
return c
}, {})
return Object.values(uniq)
}
}
// template
<div v-for="message in uniqueMessages">
<span class="grouped-date">
{{ message.created_at }}
</span>
</div>
关于javascript - VueJS v-if with 方法总是返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55344095/