vue的注意规范之v-if 与 v-for 一起使用

探讨Vue.js中v-if与v-for指令的优先级及其最佳实践,包括如何避免同时使用,利用计算属性优化渲染效率。

 

当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级,这意味着 v-if 将分别重复运行于每个 v-for 循环中

所以,不推荐v-if和v-for同时使用

使用推荐方式:

<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

或者:放在计算属性遍历

computed: {
  activeUsers: function () {
    return this.users.filter(function (user) {
      return user.isActive
    })
  }
}
<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你想为仅有的一些项渲染节点时,这种优先级的机制会十分有用,如下:

<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>

上面的代码只传递了未完成的 todos。

而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template>)上。如:


<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No todos left!</p>

 

我用cartList动态渲染页面如下: <div class="cart-item" v-for="item in cartList" :key="item.goods_id+'-'+item.goods.goods_image"> 控制台仍然报错v-for的值不唯一,本质是页面中此时还没获取到cartList,控制台报错顺序是:index.js:54 [Vue warn]: Duplicate keys detected: '10041-http://smart-shop.itheima.net/uploads/10001/20230321/5c5c095502c09a9adae70d1d691b0166.jpg'. This may cause an update error. found in ---> <CartPage> at src/views/Layout/cart.vue <LayoutIndex> at src/views/Layout/index.vue <App> at src/App.vue <Root> warn @ vue.runtime.esm.js:4469 checkDuplicateKeys @ vue.runtime.esm.js:6499 createChildren @ vue.runtime.esm.js:6317 createElm @ vue.runtime.esm.js:6228 createChildren @ vue.runtime.esm.js:6320 createElm @ vue.runtime.esm.js:6228 createChildren @ vue.runtime.esm.js:6320 createElm @ vue.runtime.esm.js:6228 patch @ vue.runtime.esm.js:6691 Vue._update @ vue.runtime.esm.js:3657 updateComponent @ vue.runtime.esm.js:3757 Watcher.get @ vue.runtime.esm.js:3351 Watcher @ vue.runtime.esm.js:3341 mountComponent @ vue.runtime.esm.js:3778 Vue.$mount @ vue.runtime.esm.js:8308 init @ vue.runtime.esm.js:4264 merged @ vue.runtime.esm.js:4426 createComponent @ vue.runtime.esm.js:6249 createElm @ vue.runtime.esm.js:6211 createChildren @ vue.runtime.esm.js:6320 createElm @ vue.runtime.esm.js:6228 patch @ vue.runtime.esm.js:6691 Vue._update @ vue.runtime.esm.js:3657 updateComponent @ vue.runtime.esm.js:3757 Watcher.get @ vue.runtime.esm.js:3351 Watcher @ vue.runtime.esm.js:3341 mountComponent @ vue.runtime.esm.js:3778 Vue.$mount @ vue.runtime.esm.js:8308 init @ vue.runtime.esm.js:4264 merged @ vue.runtime.esm.js:4426 createComponent @ vue.runtime.esm.js:6249 createElm @ vue.runtime.esm.js:6211 updateChildren @ vue.runtime.esm.js:6470 patchVnode @ vue.runtime.esm.js:6550 patch @ vue.runtime.esm.js:6696 Vue._update @ vue.runtime.esm.js:3660 updateComponent @ vue.runtime.esm.js:3757 Watcher.get @ vue.runtime.esm.js:3351 Watcher.run @ vue.runtime.esm.js:3422 flushSchedulerQueue @ vue.runtime.esm.js:4007 eval @ vue.runtime.esm.js:3064 flushCallbacks @ vue.runtime.esm.js:2992 Promise.then(异步) timerFunc @ vue.runtime.esm.js:3017 nextTick @ vue.runtime.esm.js:3074 queueWatcher @ vue.runtime.esm.js:4089 Watcher.update @ vue.runtime.esm.js:3413 Dep.notify @ vue.runtime.esm.js:814 reactiveSetter @ vue.runtime.esm.js:1027 eval @ vue-router.esm.js:2520 eval @ vue-router.esm.js:2519 updateRoute @ vue-router.esm.js:2048 eval @ vue-router.esm.js:1915 eval @ vue-router.esm.js:2037 step @ vue-router.esm.js:1763 step @ vue-router.esm.js:1770 step @ vue-router.esm.js:1770 runQueue @ vue-router.esm.js:1774 eval @ vue-router.esm.js:2032 step @ vue-router.esm.js:1763 eval @ vue-router.esm.js:1767 eval @ vue-router.esm.js:2020 eval @ vue-router.esm.js:1833 iterator @ vue-router.esm.js:2002 step @ vue-router.esm.js:1766 step @ vue-router.esm.js:1770 step @ vue-router.esm.js:1770 eval @ vue-router.esm.js:1767 eval @ vue-router.esm.js:2020 eval @ index.js:54 iterator @ vue-router.esm.js:2002 step @ vue-router.esm.js:1766 step @ vue-router.esm.js:1770 runQueue @ vue-router.esm.js:1774 confirmTransition @ vue-router.esm.js:2027 transitionTo @ vue-router.esm.js:1914 push @ vue-router.esm.js:2197 eval @ vue-router.esm.js:2545 push @ vue-router.esm.js:2544 click @ index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/views/ProductDetail/index.vue?vue&type=template&id=70b74859&scoped=true:146 invokeWithErrorHandling @ vue.runtime.esm.js:2945 invoker @ vue.runtime.esm.js:1835 original_1._wrapper @ vue.runtime.esm.js:7063 显示另外 81 个框架 收起 index.js:54 [vuex] unknown action type: cart/setCartList dispatch @ vuex.esm.js:473 boundDispatch @ vuex.esm.js:386 created @ index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/views/Layout/cart.vue?vue&type=script&lang=js:45 await in created(异步) invokeWithErrorHandling @ vue.runtime.esm.js:2945 callHook$1 @ vue.runtime.esm.js:3917 Vue._init @ vue.runtime.esm.js:5434 VueComponent @ vue.runtime.esm.js:5561 createComponentInstanceForVnode @ vue.runtime.esm.js:4409 init @ vue.runtime.esm.js:4263 merged @ vue.runtime.esm.js:4426 createComponent @ vue.runtime.esm.js:6249 createElm @ vue.runtime.esm.js:6211 createChildren @ vue.runtime.esm.js:6320 createElm @ vue.runtime.esm.js:6228 patch @ vue.runtime.esm.js:6691 Vue._update @ vue.runtime.esm.js:3657 updateComponent @ vue.runtime.esm.js:3757 Watcher.get @ vue.runtime.esm.js:3351 Watcher @ vue.runtime.esm.js:3341 mountComponent @ vue.runtime.esm.js:3778 Vue.$mount @ vue.runtime.esm.js:8308 init @ vue.runtime.esm.js:4264 merged @ vue.runtime.esm.js:4426 createComponent @ vue.runtime.esm.js:6249 createElm @ vue.runtime.esm.js:6211 updateChildren @ vue.runtime.esm.js:6470 patchVnode @ vue.runtime.esm.js:6550 patch @ vue.runtime.esm.js:6696 Vue._update @ vue.runtime.esm.js:3660 updateComponent @ vue.runtime.esm.js:3757 Watcher.get @ vue.runtime.esm.js:3351 Watcher.run @ vue.runtime.esm.js:3422 flushSchedulerQueue @ vue.runtime.esm.js:4007 eval @ vue.runtime.esm.js:3064 flushCallbacks @ vue.runtime.esm.js:2992 Promise.then(异步) timerFunc @ vue.runtime.esm.js:3017 nextTick @ vue.runtime.esm.js:3074 queueWatcher @ vue.runtime.esm.js:4089 Watcher.update @ vue.runtime.esm.js:3413 Dep.notify @ vue.runtime.esm.js:814 reactiveSetter @ vue.runtime.esm.js:1027 eval @ vue-router.esm.js:2520 eval @ vue-router.esm.js:2519 updateRoute @ vue-router.esm.js:2048 eval @ vue-router.esm.js:1915 eval @ vue-router.esm.js:2037 step @ vue-router.esm.js:1763 step @ vue-router.esm.js:1770 step @ vue-router.esm.js:1770 runQueue @ vue-router.esm.js:1774 eval @ vue-router.esm.js:2032 step @ vue-router.esm.js:1763 eval @ vue-router.esm.js:1767 eval @ vue-router.esm.js:2020 eval @ vue-router.esm.js:1833 iterator @ vue-router.esm.js:2002 step @ vue-router.esm.js:1766 step @ vue-router.esm.js:1770 step @ vue-router.esm.js:1770 eval @ vue-router.esm.js:1767 eval @ vue-router.esm.js:2020 eval @ index.js:54 iterator @ vue-router.esm.js:2002 step @ vue-router.esm.js:1766 step @ vue-router.esm.js:1770 runQueue @ vue-router.esm.js:1774 confirmTransition @ vue-router.esm.js:2027 transitionTo @ vue-router.esm.js:1914 push @ vue-router.esm.js:2197 eval @ vue-router.esm.js:2545 push @ vue-router.esm.js:2544 click @ index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/views/ProductDetail/index.vue?vue&type=template&id=70b74859&scoped=true:146 invokeWithErrorHandling @ vue.runtime.esm.js:2945 invoker @ vue.runtime.esm.js:1835 original_1._wrapper @ vue.runtime.esm.js:7063 显示另外 74 个框架 收起 index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/views/Layout/cart.vue?vue&type=script&lang=js:47 Store cartList: (5) [{…}, {…}, {…}, {…}, {…}, __ob__: Observer]0: create_time: "2025-07-07 19:46:33"goods: Objectgoods_id: 10039goods_num: 9goods_sku_id: "0"id: (…)isChecked: trueis_delete: (…)store_id: (…)update_time: (…)user_id: (…)__ob__: Observer {value: {…}, shallow: false, mock: false, dep: Dep, vmCount: 0}get create_time: ƒ reactiveGetter()set create_time: ƒ reactiveSetter(newVal)get goods: ƒ reactiveGetter()set goods: ƒ reactiveSetter(newVal)get goods_id: ƒ reactiveGetter()set goods_id: ƒ reactiveSetter(newVal)get goods_num: ƒ reactiveGetter()set goods_num: ƒ reactiveSetter(newVal)get goods_sku_id: ƒ reactiveGetter()set goods_sku_id: ƒ reactiveSetter(newVal)get id: ƒ reactiveGetter()set id: ƒ reactiveSetter(newVal)get isChecked: ƒ reactiveGetter()set isChecked: ƒ reactiveSetter(newVal)get is_delete: ƒ reactiveGetter()set is_delete: ƒ reactiveSetter(newVal)get store_id: ƒ reactiveGetter()set store_id: ƒ reactiveSetter(newVal)get update_time: ƒ reactiveGetter()set update_time: ƒ reactiveSetter(newVal)get user_id: ƒ reactiveGetter()set user_id: ƒ reactiveSetter(newVal)[[Prototype]]: Object1: {…}2: {…}3: {…}4: {…}length: 5__ob__: Observer {value: Array(5), shallow: false, mock: false, dep: Dep, vmCount: 0}[[Prototype]]: Array index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/views/Layout/cart.vue?vue&type=script&lang=js:48 Mapped cartList: (5) [{…}, {…}, {…}, {…}, {…}, __ob__: Observer],先输出报错,再输入 const { data } = await getCartList() // 2. 更新本地状态(如需要) this.mycartList = data.list await this.$store.dispatch('cart/setCartList', data.list) // 新增一个直接提交数据的 Action console.log('Store cartList:', this.$store.state.cart.cartList) // 应 data.list 一致 console.log('Mapped cartList:', this.cartList) // 应同步更新,从的console.log语句,是什么原因
07-08
评论 14
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值