Фильтр по вложенным (рекурсивным) данным (Vue 2)

#vue.js #filter #nested #lodash #children

#vue.js #Фильтр #вложенные #Lodash #дочерние элементы

Вопрос:

Вот пример моих данных в формате JSON :

 "data":[  
  {  
     "id":01,
     "name":"test",
     "parent_id":null,
     "children":[  
        {  
           "id":15,
           "name":"subChild",
           "parent_id":21,
           "children":[  
              {  
                 "id":148,
                 "name":"subSubChild",
                 "parent_id":22,
                 "children":[  
                        ....
                 ]
              }
           ]
        }
     ]
  },
  

Я хотел бы отфильтровать этот уровень по уровням. Я создал этот метод :

 computed: {
      filteredData: function () {
        let filterData = this.filter.toLowerCase()
        return _.pickBy(this.data, (value, key) => {
          return _.startsWith(value.name.toLowerCase(), filterData)
        })
      },
  

Это работает только для первого «уровня», и я попробовал несколько решений, но ни одно из них не сработало для дочерних элементов.

Итак, я хотел бы иметь возможность фильтровать по нескольким уровням.

Если у вас есть идея! Спасибо

Комментарии:

1. Каков ожидаемый результат? Объекты, которые имеют filterData as name ?

2. ДА. Для получения более подробной информации: — категория 1 — подкатегория 1-1 — категория 2 — Подкатегория 2-1 — Подкатегория 2-2 — категория 3….. Если я использую фильтр для «Подкатегории 2-2», я хотел бы видеть только «Подкатегорию 2-2» и родительскую «Категорию 2». Надеюсь, я выразился правильно! Спасибо вам

3. @Lolo Имеет ли смысл мой ответ ниже? Дайте мне знать, если я что-то пропустил, чтобы мы могли это исправить.

4. @jom конечно! Я ответил вам чуть ниже! Еще раз спасибо!!!

Ответ №1:

Рекурсивная функция может пригодиться для этой конкретной цели.

Попробуйте следующий подход, и для лучшего просмотра нажмите на Full page ссылку рядом с Run code snippet кнопкой внизу.

 new Vue({
  el: '#app',

  data() {
    return {
      filter: '',
      maintainStructure: false,
      data: [{
        "id": 01,
        "name": "test",
        "parent_id": null,
        "children": [{
          "id": 15,
          "name": "subChild",
          "parent_id": 21,
          "children": [
            {
              "id": 148,
              "name": "subSubChild",
              "parent_id": 22,
              "children": []
            }, 
            {
              "id": 150,
              "name": "subSubChild3",
              "parent_id": 24,
              "children": []
            }
          ]
        }]
      }]
    }
  },

  methods: {
    $_find(items, predicate) {
      let matches = [];

      for (let item of items) {
        if (predicate(item)) {
          matches.push(item);
        } 
        else if (item.children.length) {
          let subMatches = this.$_find(item.children, predicate);
          
          if (subMatches.length) {
            if (this.maintainStructure) {
              matches.push({
                ...item,
                children: subMatches
              });
            }
            else {
              matches.push(subMatches);
            }
          }
        }
      }

      return matches;
    },

    filterBy(item) {
      return item.name.toLowerCase().startsWith(this.filter.toLowerCase());
    }
  },

  computed: {
    filteredData() {
      return this.$_find(this.data, this.filterBy);
    }
  }
})  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <div>
    <label>Filter by <code>item.name</code>:</label>
    <input v-model.trim="filter" placeholder="e.g. subsub" />
  </div>
  
  <div>
    <label>
      <input type="checkbox" v-model="maintainStructure" /> Maintain structure
    </label>
  </div>
  
  <hr />
  
  <pre>{{filteredData}}</pre>
</div>  

Обратите внимание, что я добавляю к функции префикс с $_ , чтобы вроде как пометить ее как закрытую функцию (как рекомендуется в этом руководстве по стилю), поскольку мы не собираемся вызывать ее где-либо еще.

Комментарии:

1. Здравствуйте, действительно спасибо вам за вашу помощь! Я застрял на несколько дней .. и это работает. Хорошего дня!

2. @Lolo Нет проблем. Рад, что мы разобрались с этим. 🙂