如何避免使用v-for的元素上的v-if

时间:2018-04-07 12:02:42

标签: javascript vue.js vuejs2

我有一个像这样的文字对象:

    export default {
        pizze:{
            type:"pizze",
            typeOne:{
                title: "Pizze Rosse",
                data:[
                    {id:1,type:"pizza",name:"Margherita",price:4,ingredients:["pomodoro","mozzarella"],quantity:0,inventory:100},
                    {id:2,type:"pizza",name:"Marinara",price:3.5,ingredients:["aglio","pomodoro"],quantity:0,inventory:100},
                    {id:3,type:"pizza",name:"Salsiccia e funghi",price:6,ingredients:["salsiccia","funghi","mozzarella","pomodoro"],quantity:0,inventory:100},
                    {id:4,type:"pizza",name:"Carciofi",price:4,ingredients:["mozzarella","carciofi","pomodoro"],quantity:0,inventory:100},  
                ]
            },
            typeTwo:{
                title:"Pizze Bianche",
                data:[
                    {id:5,type:"pizza",name:"Gorgonzola e noci",price:5.50,ingredients:["gorgonzola","noci","mozzarella"],quantity:0,inventory:100},
                    {id:6,type:"pizza",name:"Stracchino e rucola",price:4.50,ingredients:["stracchino","rucola","basilico"],quantity:0,inventory:100},
                    {id:7,type:"pizza",name:"Tartufo e salsiccia",price:8,ingredients:["tartufo","salsiccia","mozzarella"],quantity:0,inventory:100},
                    {id:8,type:"pizza",name:"Zucchine e Gamberi",price:5,ingredients:["zucchine","gamberi","pomodorini"],quantity:0,inventory:100},
                ]

            }
        },
        primiPiatti:{
            type:"primiPiatti",
            typeOne:{
                title: "Primi di carne",
                data:[
                    {id:12,type:"primiPiatti",name:"Lasagne alla Bolognese",price:9,quantity:0,inventory:100},
                    {id:13,type:"primiPiatti",name:"Spaghetti alla carbonara",price:14,quantity:0,inventory:100},
                    {id:14,type:"primiPiatti",name:"pennette all'amatriciana",price:10,quantity:0,inventory:100},
                    {id:15,type:"primiPiatti",name:"paccheri salsiccia e funghi",price:12,quantity:0,inventory:100},  
                ]
            },
            typeTwo:{
                title:"Primi di pesce",
                data:[
                    {id:16,type:"primiPiatti",name:"spaghetti allo scoglio",price:8.50,quantity:0,inventory:100},
                    {id:17,type:"primiPiatti",name:"zuppa di cozze",price:14.50,quantity:0,inventory:100},
                    {id:18,type:"primiPiatti",name:"pappardelle asparagi e gamberi",price:18,quantity:0,inventory:100},
                    {id:19,type:"primiPiatti",name:"lasagne al salmone",price:15,quantity:0,inventory:100},
                ]

            },
...

我不知道使用v-if inside a v-for loop是不好的,我在视图中显示代码的第一种方法是:

<div class="menu__container">
          <div v-if="menuVoice!=='type'"class="menu__container--box" v-for="menuVoice in Object.keys(menuData)" :key="menuVoice">
              <div class="title">{{menuData[menuVoice].title}}</div>
              <item-record v-for="data in menuData[menuVoice].data" :key="data.id" :data="data"></item-record>
          </div>
        </div> 

我尝试做的是避免显示与对象type的{​​{1}}属性相关的div块。因为我需要它用于其他目的(例如检索正确的对象)。所以我用这种方式重构了代码:

MenuVoice

我不确定它是否正常,因为那里总是有一个if语句。代码适用于这两种情况,但我想知道是否有更好的方法来做这样的事情。

我也尝试将v-if移动到子div上,如下所示:

<div class="menu__container">
          <div :style="[menuVoice === 'type' ? {display:'none'} : {display:'block'}]" class="menu__container--box" v-for="menuVoice in Object.keys(menuData)" :key="menuVoice">
              <div class="title">{{menuData[menuVoice].title}}</div>
              <item-record v-for="data in menuData[menuVoice].data" :key="data.id" :data="data"></item-record>
          </div>
        </div> 

但它不起作用,因为我仍然会使用类<div class="menu__container"> <div"class="menu__container--box" v-for="menuVoice in Object.keys(menuData)" :key="menuVoice"> <div v-if="menuVoice !=='type'> <div class="title">{{menuData[menuVoice].title}}</div> <item-record v-for="data in menuData[menuVoice].data" :key="data.id" :data="data"></item-record> </div> </div> </div> 的三个div。

2 个答案:

答案 0 :(得分:2)

避免将v-ifv-for一起使用的技巧是使用计算属性过滤数据集。

在这里,我创建了一个名为menuList的计算器,用于过滤menuData,返回过滤后的浅层克隆。

computed: {
  menuList() {
    return Object.keys(this.menuData)
      .filter(key => key !== 'type')
      .reduce((res, key) => (res[key] = this.menuData[key], res), {});
  }
}

因此,您的模板只使用开箱即用的正确列表。 v-for="(item, key) in menuList"

<div class="menu__container">
  <div class="menu__container--box" v-for="(item, key) in menuList" :key="key">
      <div class="title">{{item.title}}</div>
      <item-record v-for="data in item.data" 
                   :key="data.id" :data="data"></item-record>
  </div>
</div>

应将模板逻辑保持在最低限度。任何超过对值的引用或简单赋值的东西都应该转移到计算和方法中。

答案 1 :(得分:0)

你应该避免这样做:

<div class="menu__container">
  <div v-if="menuVoice !== 'type'"class="menu__container--box" v-for="menuVoice in Object.keys(menuData)" :key="menuVoice">
    <div class="title">{{menuData[menuVoice].title}}</div>
    <item-record v-for="data in menuData[menuVoice].data" :key="data.id" :data="data"></item-record>
  </div>
</div>

您可以使用已经执行的操作来避免执行上述代码:

<div class="menu__container">
  <div :style="[menuVoice === 'type' ? {display:'none'} : {display:'block'}]" class="menu__container--box" v-for="menuVoice in Object.keys(menuData)" :key="menuVoice">
    <div class="title">{{menuData[menuVoice].title}}</div>
    <item-record v-for="data in menuData[menuVoice].data" :key="data.id" :data="data"></item-record>
  </div>
</div>