Vue v-如果不更新

Koa*_*nna 5 javascript vue.js

这是我的 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)

有人知道我做错了什么吗?

Dav*_*don 5

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)

上面的示例更接近原始问题

  • 用户是计算出来的而不是数据
  • unreadIds 最初为空

给我点赞吧!


gab*_*yes 5

你想要利用 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 会问最初的问题。

  • 根据 Linus Borg (Vue contibuter) 的这篇[帖子](https://forum.vuejs.org/t/can-compulated-property-be-a-function-which-itself-return-another-function/7572)返回函数的计算属性是可以的。关于应该做什么和不应该做什么似乎有很多未经证实的陈述,但请记住,Vue 的设计是开放和灵活的,而不是固执己见。 (4认同)