vue3中同一个元素上即使用v-if,又使用v-for时,v-if的优先级高于v-for
案例:
<body> <div id="app"> <ul> <li v-for="item in arr" v-if="item.done" :class="{todos:iten.done}" :key="item.id"> <span>{{item.task}}</span> </li> </ul> <ul> <li v-for="item in arr" v-if="!item.done" :class="{dones:!iten.done}" :key="item.id"> <span>{{item.task}}</span> </li> </ul> </div> <script> const {createApp}=Vue; createApp({ setup(){ const arr=[ {id:1,task:"吃饭",done:true}, {id:2,task:"打游戏",done:false}, {id:3,task:"学习",done:true}, {id:4,task:"游泳",done:false}, {id:5,task:"睡觉",done:true}, ] return {arr} } }).mount("#app") </script> </body>
此时报错是因为v-if的优先级比v-for的优先级高,所以在这里是item.done先执行,然后再执行item in arr,所以此时的item是获取不到的,done也就是没有的
解决方法:由于vue3中v-if优先级高于v-for,所以不能像vue2那样同一个元素上使用v-if和v-for,我们需要在li的外面套一层来执行for循环
<div id="app"> <ul> <template v-for="item in arr" :key="item.id"> <li v-if="item.done" :class="{todos:item.done}" > <span>{{item.task}}</span> </li> </template> </ul> <ul> <template v-for="item in arr" :key="item.id"> <li v-if="!item.done" :class="{dones:!item.done}" > <span>{{item.task}}</span> </li> </template> </ul> </div>
可以看出,如果在vue2中v-if和v-for在同一个元素上使用是无法直接在vue3中兼容的,所以由于语法上存在歧义,建议避免在同一个元素上使用两者
【最佳解决方法】针对v-if和v-for的使用,官方建议我们使用计算属性来处理的,这样既提高了性能,又可以兼容到vue3
<body> <div id="app"> <ul> <li v-for="item in done" :key="item.id" :class="{done:item.done}" > <span>{{item.task}}</span> </li> </ul> <ul> <li v-for="item in todo" :key="item.id" :class="{todo:!item.done}" > <span>{{item.task}}</span> </li> </ul> </div> <script> const {createApp,ref,computed} =Vue createApp({ setup(){ const show=ref(true) const arr=[ {id:1,task:"吃饭",done:true}, {id:2,task:"写作业",done:false}, {id:3,task:"午休",done:true}, {id:4,task:"睡觉",done:false}, {id:5,task:"洗澡",done:true} ] const done=computed(()=>arr.filter(t=>t.done)) const todo=computed(()=>arr.filter(t=>!t.done)) return {arr,done,todo} } }).mount('#app') </script> </body>