首页 > 解决方案 > 在 vue.js 中循环 JSON 数组的问题

问题描述

我想遍历一个 JSON 数组来搜索关键字。我正在参考这个线程来实现这一点。

条目是结构的 JSON 数组

[
    {"a": "something", "id": 54785, "b": ["each", "every", "one"]},
    {"a": "something", "id": 54785, "b": ["each", "every", "one"]},
    {"a": "something", "id": 54785, "b": ["each", "every", "one"]},
]

searchItem来自这个自定义组件

<FormInput type="text"
    v-model="searchItem"
    @input="searchObject()"
    placeholder="Search here">
</FormInput> 

我将我的功能放在这样的组件方法中。

searchObject: function() {
  for (var i=0; i<this.entries.length; i++) {
    for (var key in this.entries[i]) {
      if (this.entries[i].key.indexOf(this.searchItem)!==-1) {
        this.result.push(this.entries[i])
      }
    }
  }
  return this.result
}

我在控制台中收到此错误

TypeError: Cannot read property 'indexOf' of undefined

当我更改计算函数并尝试[key]而不是.key

searchObject() {
  for (var i=0; i<this.entries.length; i++) {
    for (var key in this.entries[i]) {
      if (this.entries[i][key].indexOf(this.searchItem)!==-1) {
        this.result.push(this.entries[i])
      }
    }
  }
  return this.result
}

我没有收到任何推送结果,也没有在控制台中收到任何错误。我试图将 console.log() 命令放在我的函数上,但控制台上也没有任何内容。

标签: vue.jsvuejs2vue-component

解决方案


假设每个对象内部没有任何深度嵌套的对象或数组,您可以使用它Object.values来获取对象的值。

对于您当前的数据,返回的值将包含另一个数组,因此您必须通过.concat.apply将值合并到一个数组中来将其展平。

使用扁平化数组,您可以轻松检查当前对象是否包含您的searchItem.

编辑:如果您想在结果中包含searchItem与项目值的某些部分匹配的项目,您可以使用.join将您的展平值连接到一个字符串中。

请参见下面的示例:

var app = new Vue({
  el: '#app',
  data: {
    result: [],
    searchItem: '',
    entries: [{
        "a": "something",
        "id": 54785,
        "b": ["one", "two", "three"]
      },
      {
        "a": "nothing",
        "id": 54785,
        "b": ["each", "every", "one"]
      },
      {
        "a": "everything",
        "id": 54785,
        "b": ["each", "every", "one"]
      },
    ]
  },
  methods: {
    searchObject: function() {
      this.result = []; // clear data, for demonstration only, remove if not needed

      for (var i = 0; i < this.entries.length; i++) {
        var values = [].concat.apply([], this.getValues(this.entries[i]));
        
        // you can also convert it to a string to match certain string parts
        values = values.join(',');
        
        if (values.indexOf(this.searchItem) !== -1) {
          this.result.push(this.entries[i])
        }
      }
    },
    getValues: function(object) {
      // use a polyfill in case Object.values is not supported by current browser
      return Object.values ? Object.values(object) : Object.keys(object).map(key => object[key]);
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<div id="app">
  <input type="text" v-model="searchItem" v-on:input="searchObject" placeholder="Search here" />
  <ul>
    <li v-for="i in result">{{i}}</li>
  </ul>
</div>


推荐阅读