#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
asname
?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 Нет проблем. Рад, что мы разобрались с этим. 🙂