【问题标题】:Vue v-if not updatingVue v-如果不更新
【发布时间】:2020-04-25 07:12:16
【问题描述】:

这是我的 Vue 模板的一部分:

<ul>
   <li v-for="friend in user.friends">
       <span v-if="checkIfNew(friend.id)"> ... </span>
   </li>
</ul>

基本上,friends 是一个对象数组,如果我们有来自其中任何一个的新消息,我想显示 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;
    }
}

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

【问题讨论】:

  • 告诉我们你如何更新unreadIds
  • @Ohgodwhy 它在 apollo $subscribe 部分,结果是:this.unreadIds.push(...)。我知道数组本身正在正确更新。
  • 当您说“v-if 不会对更改做出反应。”时,这不是必需的,因为它在循环内。您需要的是循环对更改做出反应,这意味着进行计算,例如 friends() { return this.user.friends } 并以此为基础循环。
  • @eric99 感谢 x2 unreadIds 是朋友的 id,他们发送了一条新消息。我会编辑这个问题,这真的很混乱
  • @RichardMatsen 消息不会影响朋友。因此,当新消息到达时,朋友不会改变。所以循环是基于朋友的,但我希望它也能对 unreadIds 做出反应......

标签: javascript vue.js


【解决方案1】:

id in this.unreadIds 并没有按照你的想法去做。请参阅in operator 的文档。如果对象具有该值作为属性,它将返回true。因此,如果 this.unreadIds 有 3 个项目并且您的 id 为 1,则 in 运算符将返回 true,因为 1 是数组的属性(this.unreadIds[1] 存在)。

您应该使用includes

尝试像这样重写你的方法:

checkIfNew(id) {
  return this.unreadIds.includes(id);
}

这是一个没有 Vuex 商店代码的更新列表的组件的工作版本:

<ul>
  <li v-for="friend in user.friends" :key="friend.ids">
    <span v-if="checkIfNew(friend.id)">{{ friend.name }}</span>
  </li>
</ul>
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);
    },
  },
};

这里只是为了证明大卫一直都是正确的,我把这段代码放在一个可运行的sn-p中,找不到任何错误...

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' }
        ]
      }
    }
  }
})
<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>

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

  • 用户是计算的非数据
  • unreadIds 最初为空

给我点赞!

【讨论】:

【解决方案2】:

您想利用 Vue 的反应性系统,因为前面的答案没有。它们最终会让您遇到难以调试的莫名其妙的问题。

而不是在 v-for 中调用方法(我保证将来会给您带来问题),您应该声明一个包含(或不包含)您想要呈现的项目的计算列表,就像这样:

data(){
   return {
      unreadIds: []
   }
},
computed:{
    user(){
      return this.$store.getters.user;
    },
    NewFriends() {
       return this.user.friends.filter(friend => this.unreadIds.includes(friend.id));
    }
}

您的标记将是:

<ul>
   <li v-for="friend in NewFriends">
       <span > ... </span>
   </li>
</ul>

而且 Vue 的反应性系统会处理 NewFriends 的数据依赖关系的任何更改。

您永远不想在模板中使用方法调用,因为方法调用只能保证被调用一次(这同样适用于来自计算方法的函数...)。

如果您发现自己试图手动触发重新渲染和依赖性检查,您将需要重新考虑您的设计。

ETA:您唯一需要在模板中调用任何类型的函数是响应事件。

【讨论】:

  • +1 与其他答案相比,这是最佳实践!官方style guide也推荐这个。
【解决方案3】:

我会试一试 - 有人早些时候发布了这个并删除了它。您需要 checkIfNew() 是计算而不是模板中的反应性方法。

由于需要传入id,计算需要返回一个函数。

data(){
   return {
      unreadIds: []
   }
},
computed:{
    user(){
      return this.$store.getters.user;
    },
   checkIfNew(){
      return (id) => {
        return this.unreadIds.includes(id);
      }
   }
}

正如 David Weldon 所说,理想情况下,您应该不可变地更改数组 - 这可能是为什么 ohgodwhy 会问原始问题。

【讨论】:

  • 依赖检查的假行是否必要?
  • @user1538301 ...其实不是
  • 看起来有点hacky。
  • 只是让 checkIfNew() 计算修复它
  • 根据 post 由 Linus Borg(Vue 参与者)计算的返回函数的属性是可以的。关于应该做什么和不应该做什么似乎有很多未经证实的陈述,但请记住,Vue 的设计是开放和灵活的,而不是固执己见。
猜你喜欢
  • 2017-09-09
  • 2021-05-25
  • 2021-05-19
  • 2019-04-16
  • 2019-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-12
相关资源
最近更新 更多