这是我的 Vue 模板的一部分:
<ul>
<li v-for="friend in user.friends">
<span v-if="checkIfNew(friend.id)"> ... </span>
</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
基本上,朋友是一个对象数组,如果我们有来自其中任何一个的新消息,我想显示 span 元素。就是这样checkIfNew()。检查好友的 id 是否在数组中unreadIds(包含发送消息的好友的 id)
该数组正在以不同的方法进行更新,但是,问题是:v-if不对更改做出反应。
这是脚本部分的一部分:
data(){
return {
unreadIds: []
}
},
methods:{
checkIfNew(id){
if(id in this.unreadIds) return true
else return false
}
},
computed:{
user(){
return this.$store.getters.user;
}
}
Run Code Online (Sandbox Code Playgroud)
有人知道我做错了什么吗?
id in this.unreadIds不做你认为它做的事。请参阅in 运算符的文档。true如果对象具有作为属性的值,它将返回。因此,如果this.unreadIds有 3 个项目,并且您的 id 为1,则in运算符将返回true,因为1是 数组的属性(this.unreadIds[1]存在)。
相反,您应该使用include。
尝试像这样重写你的方法:
checkIfNew(id) {
return this.unreadIds.includes(id);
}
Run Code Online (Sandbox Code Playgroud)
这是该组件的工作版本,无需 Vuex 存储代码即可更新列表:
<ul>
<li v-for="friend in user.friends" :key="friend.ids">
<span v-if="checkIfNew(friend.id)">{{ friend.name }}</span>
</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
export default {
data() {
return {
unreadIds: [5],
user: {
friends: [
{ id: 1, name: 'joe' },
{ id: 5, name: 'nancy' },
{ id: 9, name: 'sue' },
],
},
};
},
created() {
setTimeout(() => this.unreadIds.push(9), 2000);
},
methods: {
checkIfNew(id) {
return this.unreadIds.includes(id);
},
},
};
Run Code Online (Sandbox Code Playgroud)
只是为了在这里证明大卫一直都是正确的,我把这段代码放在一个可运行的片段中,并且找不到任何错误......
Vue.config.productionTip = false
new Vue({
el: '#app',
data() {
return {
unreadIds: [],
};
},
created() {
setTimeout(() => this.unreadIds.push(9), 2000);
},
methods: {
checkIfNew(id) {
// if(id in this.unreadIds) return true
// else return false
return this.unreadIds.includes(id);
},
},
computed: {
user(){
return {
friends: [
{ id: 1, name: 'joe' },
{ id: 5, name: 'nancy' },
{ id: 9, name: 'sue' }
]
}
}
}
})Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<div id="app">
<ul>
<li v-for="friend in user.friends" >
<span v-if="checkIfNew(friend.id)">{{ friend.name }}</span>
</li>
</ul>
</div>Run Code Online (Sandbox Code Playgroud)
上面的示例更接近原始问题
给我点赞吧!
你想要利用 Vue 的反应系统,因为之前的答案没有......它们最终会让你遇到难以解释的难以调试的问题。
您应该声明一个包含v-for(或不包含)您想要渲染的项目的计算列表,而不是调用 a 中的方法(我保证这将来会给您带来问题),如下所示:
data(){
return {
unreadIds: []
}
},
computed:{
user(){
return this.$store.getters.user;
},
NewFriends() {
return this.user.friends.filter(friend => this.unreadIds.includes(friend.id));
}
}
Run Code Online (Sandbox Code Playgroud)
那么您的标记将是:
data(){
return {
unreadIds: []
}
},
computed:{
user(){
return this.$store.getters.user;
},
NewFriends() {
return this.user.friends.filter(friend => this.unreadIds.includes(friend.id));
}
}
Run Code Online (Sandbox Code Playgroud)
Vue 的反应系统将处理NewFriends.
您不想在模板中使用方法调用,因为方法调用只能保证被调用一次(这同样适用于来自计算方法的函数......)。
如果您发现自己试图手动触发重新渲染和依赖性检查,您将需要重新考虑您的设计。
ETA:您唯一想要调用模板中任何类型的函数的时候就是响应事件。
小智 1
我会尝试一下 - 有人早些时候发布过此内容并删除了它。您需要checkIfNew()成为模板中反应性的计算方法而不是方法。
由于需要传入id,所以compute需要返回一个函数。
data(){
return {
unreadIds: []
}
},
computed:{
user(){
return this.$store.getters.user;
},
checkIfNew(){
return (id) => {
return this.unreadIds.includes(id);
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如 David Weldon 所说,理想情况下,您应该一成不变地更改数组 - 以及为什么 ohgodwhy 会问最初的问题。