【问题标题】:Vuejs how to display Div if an array contains a value如果数组包含值,Vuejs如何显示Div
【发布时间】:2020-02-04 17:53:15
【问题描述】:

我正在尝试根据数组的内容显示图像。

我正在为自助餐厅构建一个类似页面的菜单。我需要显示每个项目的过敏原,但如果它包含在过敏原数组中,我不知道如何使用 v-if 来显示包含相应过敏原图像的 div。我正在从我无法控制的 api 中提取所有数据。这是 api 返回的示例。

{
"location_id": "Cannon",
"serve_date": "20200204",
"meal_name": "BREAKFAST",
"category": "Euro Kitchen",
"name": "Chorizo & Egg Chilaquiles",
"serving_size": "1 each (229.50g)",
"nutrients": [
{
"name": "Calories",
"measurement": "kcal",
"amount": 477.2
},
{
"name": "Total Fat",
"measurement": "g",
"amount": 30.73
},
{
"name": "Saturated Fat",
"measurement": "g",
"amount": 12.55
},
{
"name": "Trans Fat",
"measurement": "g",
"amount": 0
},
{
"name": "Cholesterol",
"measurement": "mg",
"amount": 433.25
},
{
"name": "Sodium",
"measurement": "mg",
"amount": 900.56
},
{
"name": "Carbohydrates",
"measurement": "g",
"amount": 23.57
},
{
"name": "Total Fiber",
"measurement": "g",
"amount": 2.2
},
{
"name": "Total Sugars",
"measurement": "g",
"amount": 2.25
},
{
"name": "Protein",
"measurement": "g",
"amount": 25.22
},
{
"name": "Vitamin A",
"measurement": "iu",
"amount": 1310.47
},
{
"name": "Vitamin C",
"measurement": "mg",
"amount": 1.68
},
{
"name": "Calcium",
"measurement": "mg",
"amount": 271.25
},
{
"name": "Iron",
"measurement": "mg",
"amount": 2.85
},
{
"name": "Water",
"measurement": "g",
"amount": 3.76
},
{
"name": "Ash",
"measurement": "g",
"amount": 0.05
},
{
"name": "Potassium",
"measurement": "mg",
"amount": 160.63
},
{
"name": null,
"measurement": null,
"amount": 42.87
}
],
"allergens": [
"Milk",
"Egg",
"Corn",
"MSG"
],
"ingredients": "Scrambled Eggs (Liquid Eggs (Whole Eggs; Citric Acid; Water); Cheddar Cheese (Pasteurized Milk; Salt; Enzymes; Annatto); Salt; Black Pepper); Tortilla Chips (Corn Cooked with Lime Water; Water; Cellulose Gum; Guar Gum; Sodium Propionate; Propionic Acid; Sodium Hydroxide; Fumaric Acid; Sorbic; Methyparanen; Propylparaben); Chorizo Sausage (Pork; Vinegar; Water; Chili Peppers; Salt; Paprika; Spices; Oleoresin Paprika; Garlic Powder; Onion Powder; Sugar; Autolyzed Yeast; Oleoresin Capsicum; Natural Flavors; Natural Smoke Flavor); Enchilada Sauce (Tomato Puree; Water; Red Chili Puree; Salt; Chili Pepper; Canola Oil; Onion Powder; Spices; Garlic Puree; Oleoresin Paprika; Pectin; Cornstarch; Natural Flavor; Lemon Juice Concentrate; Citric Acid; Guar Gum; Xanthan Gum; Garlic Powder; Autolyzed Yeast Extract; Locust Bean Gum); Green Onions; Cotija Cheese (Pasteurized Whole Milk; Salt; Rennet; Enzymes; Cellulose)",
"header": false,
"special_diets": [
"Vegetarian"
]
},

在这个 sn-p 的基础上有一个称为过敏原的字段。在网站上,我有与这些项目中的每一个相匹配的相应图像。例如

img src="./images/Wheat_icon.png"

当且仅当数组包含该过敏原时,我才想显示此图标。

我试图这样做:

<div class="nutrition-allergen-icon" v-if="'displayedContains(egg)'">
                <img class="nutrition-allergen-img" 
                src="./images/Egg_icon.png"></div>

methods: {
displayedContains: function (item) {
    console.log("hit")
    for(allergen in this.displayedItem) { 
      if(allergen == item)
      return true;
    }
    return false;
  },
}

我也试过了:

computed: {
    displayedContains: function (item) {
        console.log("hit")
        for(allergen in this.displayedItem) { 
          if(allergen == item)
          return true;
        }
        return false;
      },
    }

我需要它是一个函数,因为如果过敏原数组中有许多不同的坚果中的任何一种,就会显示坚果的过敏原图标。

【问题讨论】:

  • egg v-if="'displayedContains(egg)'" 来自哪里?

标签: vue.js


【解决方案1】:

我想我有一个解决方案,但它与您在那里尝试的有点不同。

您可以使用您的方法检索过敏原的图像,而不是检查它是否存在。

所以你的模型中会有这样的东西:

data() {
    return {
       ...
    }
},
methods: {
    getAllergenImage(allergen) {
        switch (allergen) {
            case 'Egg':
                return 'Egg_icon.jpg';
            case 'Milk':
                return 'Milk_icon.jpg';
        }
    }
}

或者,如果您可以控制图像图标的名称,您可以只命名它们,这样就不需要 switch 语句:

methods: {
    getAllergenImage(allergen) {
       return `${allergen}_icon.jpg`;
    }
}

然后,当您到达需要显示过敏原图像的应用部分时,只需遍历过敏原数组并使用您的新方法查找相应的图像:

<div class="nutrition-allergen-icon" v-for="allergen in allergens">
    <img class="nutrition-allergen-img" :src="'./images/' + getAllergenImage(allergen)">
</div>

这是一个工作示例的代码笔:

https://codepen.io/kburlz/pen/PoqYOrQ

【讨论】:

  • 我最终选择了这个解决方案,因为我需要对默认情况进行更多控制。谢谢!
【解决方案2】:

如果你使用一个对象来存储过敏原字符串和它们对应的图像之间的关系呢?像这样的:

  allergenLookup: {
      Egg: 'egg_image.png',
      Milk: 'milk_image.png',
      Corn: 'corn_image.png',
      Peanut: 'nut_image.png',
      Walnut: 'nut_image.png',
      Almond: 'nut_image.png',
      MSG: 'msg_image.png'
      ...
  },

这样您就可以遍历过敏原并显示正确的图像,如下所示:

<div class="nutrition-allergen-icon" v-for="allergen in foodItem.allergens">
  <img class="nutrition-allergen-img" :src="'./images/' + allergenLookup[allergen]">
</div>

另外,一个非常假的例子,这里有文字而不是图片: https://jsfiddle.net/ebbishop/6x9bonh4/

【讨论】:

  • 感谢您的及时回复,像冠军一样工作!
【解决方案3】:

我认为您的 sn-p 不清楚,但是您可以应用此逻辑进行条件渲染:

new Vue({
  el: '#app',

  data() {
    return {
      ingredients: [
        { name: 'foo' },
        { name: 'egg' },
        { name: 'bar' }
      ],
      allergens: [
        "Milk",
        "Egg",
        "Corn",
        "MSG"
      ],
      allergensLowerCase: []
    }
  },

  created () {
    this.allergensLowerCase = this.allergens.map(allergen => allergen.toLowerCase());
  },

  methods: {
    displayedContains (item) {
      const itemLowerCase = item.toLowerCase()
      return this.allergensLowerCase.includes(itemLowerCase) // returns true | false
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>

<div id="app">
  <template 
    v-for="ingredient in ingredients"
  >
    <div
      v-if="displayedContains(ingredient.name)"
      class="nutrition-allergen-icon"
    >
      {{ ingredient.name }}
      <img 
        class="nutrition-allergen-img" 
        src="./images/Egg_icon.png"
      >
    </div>
  </template>
</div>

或使用计算属性进行过滤:

new Vue({
  el: '#app',

  data() {
    return {
      ingredients: [
        { name: 'foo' },
        { name: 'egg' },
        { name: 'bar' },
      ],
      allergens: [
        "Milk",
        "Egg",
        "Corn",
        "MSG"
      ],
      allergensLowerCase: []
    }
  },

  created () {
    this.allergensLowerCase = this.allergens.map(allergen => allergen.toLowerCase());
  },

  computed: {
    filteredIngredients() {
      return this.ingredients.filter(ingredient => this.allergensLowerCase.includes(ingredient.name.toLowerCase()))
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>

<div id="app">
  <div
    v-for="(ingredient, index) in filteredIngredients" :key="index"
    class="nutrition-allergen-icon"
  >
    {{ ingredient.name }}
    <img 
      class="nutrition-allergen-img" 
      src="./images/Egg_icon.png"
    >
  </div>
</div>

对于src 图像:

src="`./images/${ingredient.name}_icon.png`"

【讨论】: