【问题标题】:How to filter results using "v-for" in Vue.JS如何在 Vue.JS 中使用“v-for”过滤结果
【发布时间】:2020-02-05 15:24:10
【问题描述】:

我正在使用使用 Bootstrap-Vue 构建的选项卡式界面。单击其中一个选项卡时,我使用 v-for 在显示为网格的手风琴/下拉列表中呈现一些数据。

目前,我有一个显示所有结果的选项卡,在使用以下内容时可以正常工作 (注意:prizesData 是我使用 axios 调用后存储 response.data 的位置):

<div class="col-sm-12 col-md-6 col-lg-3 w-100 prize-dropdown-wrapper pb-5"
 v-for="(prize, name, index) in prizesData"
 :key="index"
>
<!--REMAINDER OF MARKUP GOES HERE-->
</div>

我的 JSON 结构看起来像这样,除了我总共有 43 个结果。每个对象中的每个值都会改变,但我想使用 prizeType1Name 和 prizeType2Name 来检查它们是否包含字符串“CTW”、“IW”或“OG”:

{
  "1": [
      {
         "prizeTitle": "",
         "prizeImage": "",
         "prizeFirstLineText": "",
         "prizeType1": {
            "Image": "",
            "Line1": "",
            "Line2": ""
         },
         "prizeType2": {
            "Image": "",
            "Line1": "",
            "Line2": ""
         },
         "prizeTermsText": "",
         "prizeType1Name": "CTW",
         "prizeType2Name": ""
      }
   ],
  "2": [
      {
         "prizeTitle": "",
         "prizeImage": "",
         "prizeFirstLineText": "",
         "prizeType1": {
            "Image": "",
            "Line1": "",
            "Line2": ""
         },
         "prizeType2": {
            "Image": "",
            "Line1": "",
            "Line2": ""
         },
         "prizeTermsText": "",
         "prizeType1Name": "IW",
         "prizeType2Name": ""
      }
   ]
}

要访问我正在使用的这些值中的任何一个:

this.prizesData[name][0].prizeType1 或 this.prizesData[name][0].prizeType2

我很难理解如何过滤我的结果。例如,如果我单击名为 (CTW) 的选项卡,我只想显示 JSON 文件中包含“CTW”的结果。或者,如果单击名为“IW”的选项卡,则结果应该是包含“IW”的对象。

我尝试过的:

添加了 filteredPrizes 以将过滤后的奖品存储为对象以供以后访问

data() {
    return {
      prizesData: {},
      filteredPrizes: {},
    };
  }

我尝试在从 JSON 文件收到的现有 prizesData 对象上使用 filter(),我在获取 JSON 的相同方法中添加了它文件。

getPrizesInfo() {
      const self = this;
      //Get Error Validation JSON
      axios
        .get("/data/prizes.json")
        .then(response => (this.prizesData = response.data));

      this.filteredPrizes = this.prizesData.filter(prize =>
        this.prizesData[name][0].prizeType1.includes("CTW")
      );
    }

我的期望: 我有 4 个选项卡,第一个工作正常(显示全部)。其他 3 个需要仅显示过滤结果,具体取决于 prizeType1Name 中是否存在“CTW”、“IW”或“OG” 或 prizeType2Name。

【问题讨论】:

  • 您是否尝试过使用计算属性?
  • 我最初确实尝试过,但我不确定如何构建它或确切返回什么
  • 您可以控制 JSON 吗?在我看来,将它作为一个数组而不是一个对象会更有意义。这样可以更轻松地进行迭代以获得所需的过滤。
  • 我同意,很遗憾,我必须按原样使用 JSON
  • @ImranR 您应该使用计算属性。这就是他们的设计目的。在你理解这个概念之前不应该做太多的实验。今晚晚些时候我可能有时间发布一个示例。

标签: javascript vue.js bootstrap-vue


【解决方案1】:

我不确定我是否理解正确,但你可以试试:

new Vue({
  el: '#app',

  data() {
    return {
      myData: {
        prizeTitle: '',
        prizeImage: '',
        prizeFirstLineText: '',
        prizeType1: {
          Image: 'CTW',
          Line1: 'CTW',
          Line2: 'CTW'
        },
        prizeType2: {
          Image: 'IW',
          Line1: 'IW',
          Line2: 'IW'
        },
        prizeTermsText: '',
        prizeType1Name: 'CTW',
        prizeType2Name: 'IW'
      },
      prizesData: {}
    }
  },

  methods: {
    filter (criteria) {
      // getting keyName with value equals to criteria
      const key = 
          Object.keys(this.myData)
            .filter(key => this.myData[key] === criteria)
              .pop().replace('Name', '')

      this.prizesData = this.myData[key]
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="app">
  <button @click="filter('CTW')">CTW</button>
  <button @click="filter('IW')">IW</button>
  <pre>{{ prizesData }}</pre>
</div>

【讨论】:

  • 我怎样才能适应这个,所以我只检查prizeType1Name 或prizeType2Name 是否包含标准?我目前收到“TypeError:无法读取未定义的属性'replace'。”
  • 我不知道你的所有情况下的数据结构如何
  • 我的 JSON 文件的数据结构,正是我在我的问题中展示的,除了我展示的 43 个而不是 2 个。 “prizeType1Name”和“prizeType2Name”会说“CTW”、“IW”或“OG”。如果它们位于用户界面的 CTW 选项卡上,那么我只希望显示在“prizeType1Name”或“prizeType2Name”中显示“CTW”的那些。要访问其中任何一个,我使用: this.prizesData[name][0].prizeType1 或 this.prizesData[name][0].prizeType2
  • @ImranR 我建议在问题中添加此评论的重新措辞版本,特别是您有 2 个要评估的键。
【解决方案2】:
  • 让您的 filteredPrizes 成为计算属性
  • 为您的标准创建一个对象数组(可能已重构该想法以满足您的需求或更动态)
// Inside data
filterCriteria: [
  { name: 'prizeType1Name', value: 'CTW' },
  { name: 'prizeType2Name', value: 'CTW' }
];
  • 创建一个函数以返回一个对象数组
    • 创建一个空数组以将我们的选择推送到
    • 按键循环浏览奖品对象
    • 在循环内部,遍历标准
    • 将选择分配给数组,前提是它不存在
    • 返回数组
// Inside methods
getFilteredPrizes(prizes, criteria) {
  selected = [];

  Object.keys(prizes).forEach(a => {
    criteria.forEach(b => {
      if (prizes[a][0][b.name] === b.value && !selected.contains(prizes[a][0])) {
        selected.push(prizes[a][0]);
      }
    });
   });

   return selected;
}

new Vue({
  el: '#app',
  data() {
    return {
      prizesData: {
        "1": [
            {
               "prizeTitle": "",
               "prizeImage": "",
               "prizeFirstLineText": "",
               "prizeType1": {
                  "Image": "",
                  "Line1": "",
                  "Line2": ""
               },
               "prizeType2": {
                  "Image": "",
                  "Line1": "",
                  "Line2": ""
               },
               "prizeTermsText": "",
               "prizeType1Name": "CTW",
               "prizeType2Name": ""
            }
         ],
        "2": [
          {
             "prizeTitle": "",
             "prizeImage": "",
             "prizeFirstLineText": "",
             "prizeType1": {
                "Image": "",
                "Line1": "",
                "Line2": ""
             },
             "prizeType2": {
                "Image": "",
                "Line1": "",
                "Line2": ""
             },
             "prizeTermsText": "",
             "prizeType1Name": "IW",
             "prizeType2Name": ""
          }
       ]
      },
      filterCriteria: [
        { name: 'prizeType1Name', value: 'CTW' },
        { name: 'prizeType2Name', value: 'CTW' }
      ]
    }
  },
  computed: {
    filteredPrizes() {
      return this.getFilteredPrizes(this.prizesData, this.filterCriteria);
    }
  },
  methods: {
    getFilteredPrizes(prizes, criteria) {
      selected = [];

      Object.keys(prizes).forEach(a => {
        criteria.forEach(b => {
          if (prizes[a][0][b.name] === b.value && !selected.includes(prizes[a][0])) {
            selected.push(prizes[a][0]);
          }
        });
      });

      return selected;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="app">
  <h3>Filtered Prizes</h3>
  <pre>{{ filteredPrizes }}</pre>
</div>

【讨论】:

    【解决方案3】:

    正如@seantunwin 所建议的,我将我的 JSON 从一个对象更改为一个数组 - 需要进行一些整理和格式化,但从长远来看会让生活更轻松。

    所以我的新结构现在看起来像这样:

    [
    
    {
    
    "id": 1,
    
    "prizeTitle": "",
    
    "prizeImage": "",
    
    "prizeFirstLineText": "",
    
    "prizeType1": {
    
    "Image": "",
    
    "Line1": "",
    
    "Line2": ""
    
    },
    
    "prizeType2": {
    
    "Image": "",
    
    "Line1": "",
    
    "Line2": ""
    
    },
    
    "prizeTermsText": "",
    
    "prizeType1Name": "CTW",
    
    "prizeType2Name": ""
    
    }
    
    ]
    

    然后我使用了@Our_Benefactors 建议的计算属性,如下所示:

    computed: {
    
    filteredPrizesByQuery: function() {
    
    *return* this.prizes.filter(prize => {
    
    *return* (
    
    prize.prizeType1Name.match(this.query) ||
    
    prize.prizeType2Name.match(this.query)
    
    );
    
    });
    
    }
    
    }
    

    我使用 v-for 包装了我想要循环的代码并引用了计算属性:

    <div
    
    class="col-sm-12 col-md-6 col-lg-3 w-100 prize-dropdown-wrapper pb-5"
    
    v-for="(prize, index) in filteredPrizesByQuery"
    
    :key="index"
    
    >
    
    I set query as an empty string as default in data
    
    data() {
    
    *return* {
    
    query: "",
    
    prizes: [],
    
    }
    
    };
    

    我在选项卡上添加了一个点击事件来更改查询值,类似于@christiancarrillo 回答

    <b-tab title="IW" @click="query='IW'">
    

    所以现在当我单击一个选项卡时,值会更改为 CTW、IW 或 OG,计算的属性会检查这些值并返回与查询匹配的结果。

    【讨论】:

      猜你喜欢
      • 2019-05-07
      • 2017-09-20
      • 2020-11-07
      • 2019-02-27
      • 2020-05-15
      • 1970-01-01
      • 2018-01-21
      • 2021-05-17
      • 1970-01-01
      相关资源
      最近更新 更多