具有多个条件的过滤器数组,其中一些可以为空
Filter array with multiple conditions and that some of them can be null
我有一个用于呈现 vuetify v-list 的 JS 文件,它可以有 2 个级别(带有子节点的节点,这些是可选的)。
我需要从用户输入的搜索框中添加过滤器,我可以过滤第一级,但第二级有问题,因为有时他们有 属性 "children" null 和其他时候他们有价值。菜单是这样的:
const Menu = [
{
heading: null,
icon: "mdi-security",
text: "Login",
url: {
name: "login"
},
exactUrl: false,
children: null,
meta: {
publicPath: true
}
},
{
heading: null,
icon: "search",
text: "Lista de Funcionarios",
url: {
name: "home"
},
exactUrl: true,
children: null,
meta: {
publicPath: true
}
},
{
heading: {
text: "Mantenimientos",
publicPath: false
},
icon: null,
text: "",
url: null,
exactUrl: null,
children: null,
meta: null
},
{
heading: null,
icon: "mdi-account-group",
text: "Departamentos",
url: {
name: "departamentos"
},
exactUrl: false,
children: null,
meta: {
publicPath: false
}
},
{
heading: null,
icon: "mdi-account-circle",
text: "Funcionarios",
url: {
name: "funcionarios"
},
exactUrl: false,
children: null,
meta: {
publicPath: false
}
},
{
heading: null,
icon: "settings",
text: "Operación",
url: null,
exactUrl: false,
children: [{
icon: "add",
text: "Cargar Pedidos",
url: {
name: "departamentos"
}
},
{
icon: "playlist_add_check",
text: "Aprobar Pedidos",
url: {
name: "areas"
}
},
{
icon: "content_copy",
text: "Remitir Pedidos",
url: {
name: "maps"
}
}
],
meta: null
},
];
export default Menu;
我的计算函数是这样的:
filteredMenu() {
return this.menus.filter(menu =>
menu.text.toLowerCase().includes(this.search.toLowerCase())
);
}
如何在两个级别上同时过滤?
编辑 1:
预期结果:
如果我是对的,你想检查它的 children 是否也不是空的?您可以使用 &&
filteredMenu() {
return this.menus.filter(menu =>
menu.children && menu.text.toLowerCase().includes(this.search.toLowerCase())
);
}
创建一个可以递归调用的函数。
methods: {
filterMenuItems(menuItems) {
return menuItems.filter(menuItem => {
let found = menuItem.text.toLowerCase().includes(this.search.toLowerCase());
if (!found && Array.isArray(menuItem.children)) {
found = this.filterMenuItems(menuItem.children);
}
return found;
});
}
}
现在你的计算 属性 可以 return this.filterMenuItems(this.menus)
filteredMenu() {
return this.filterMenuItems(this.menus);
}
这也允许无限的子级别
您可以使用 Destructuring assignment in order to get a value and set a predefined value, then using Some 您可以检查 Array
上的 truthy
条件。
所以换句话说,你需要做的是:
filteredMenu() {
return this.menus.filter(menu => {
// check if the parent has the value
const parentIncludesText = menu.text.toLowerCase().includes(this.search.toLowerCase())
// define a predefined value in case 'children' is null
const { children = [] } = menu || {}
// check if some of the childs has the value.
const childrenIncludesText = children.some(child => child.text.toLowerCase().includes(this.search.toLowerCase()))
// then return the result of the parent and the children.
return parentIncludesText || childrenIncludesText
});
}
您可以使用一个有用的函数 _isExist()
const _isExist = (menu, value) => menu.text.toLowerCase().includes(value.toLowerCase())
如果存在,您可以使用它在子数组中搜索
filteredMenu() {
return this.menus.filter(
menu =>
_isExist(menu, this.search) ||
(menu.children && menu.children.some(childMenu => _isExist(childMenu, this.search))),
)
}
我想你正在寻找这样的东西,它当然使用递归。不过,它使用递归的方式很重要,这意味着您要先探测 children ,然后确定是否存在 children(保留 parent), or 如果当前菜单项有给定的文本,它匹配。对于任何匹配的 children,您需要 parent,一直向内搜索菜单结构的每个分支,然后返回到 root-level 项。
这将调用 children 上的探测器,然后进一步向内运行整个过程,直到没有 children,返回每个向内的匹配集(并且它与 parent 项目),然后备份到下一个更高级别的工作。像这张图一样想,
1 match
2 match
3az < match
3ay < match
3ax < match
3a < [...match] match
3b < match
3 [...match] match
4a < match
4 [...match] match
5 match
另外,你不想过滤,你想减少到一个集合。
const search = (items, text) => {
const hasText = item => item.text.toLowerCase().includes(text.toLowerCase())
const probe = (found, item) => {
item.children = (item.children || []).reduce(probe, [])
if (item.children.length || hasText(item)) {
found.push(item)
}
return found
}
return items.reduce(probe, [])
}
... elsewhere ...
return search(this.menus, 'c')
https://jsfiddle.net/81wkh5df/6/
这个returns:
- 功能列表
- 职能部门
- 操作
- Cargar Pedidos
我有一个用于呈现 vuetify v-list 的 JS 文件,它可以有 2 个级别(带有子节点的节点,这些是可选的)。
我需要从用户输入的搜索框中添加过滤器,我可以过滤第一级,但第二级有问题,因为有时他们有 属性 "children" null 和其他时候他们有价值。菜单是这样的:
const Menu = [
{
heading: null,
icon: "mdi-security",
text: "Login",
url: {
name: "login"
},
exactUrl: false,
children: null,
meta: {
publicPath: true
}
},
{
heading: null,
icon: "search",
text: "Lista de Funcionarios",
url: {
name: "home"
},
exactUrl: true,
children: null,
meta: {
publicPath: true
}
},
{
heading: {
text: "Mantenimientos",
publicPath: false
},
icon: null,
text: "",
url: null,
exactUrl: null,
children: null,
meta: null
},
{
heading: null,
icon: "mdi-account-group",
text: "Departamentos",
url: {
name: "departamentos"
},
exactUrl: false,
children: null,
meta: {
publicPath: false
}
},
{
heading: null,
icon: "mdi-account-circle",
text: "Funcionarios",
url: {
name: "funcionarios"
},
exactUrl: false,
children: null,
meta: {
publicPath: false
}
},
{
heading: null,
icon: "settings",
text: "Operación",
url: null,
exactUrl: false,
children: [{
icon: "add",
text: "Cargar Pedidos",
url: {
name: "departamentos"
}
},
{
icon: "playlist_add_check",
text: "Aprobar Pedidos",
url: {
name: "areas"
}
},
{
icon: "content_copy",
text: "Remitir Pedidos",
url: {
name: "maps"
}
}
],
meta: null
},
];
export default Menu;
我的计算函数是这样的:
filteredMenu() {
return this.menus.filter(menu =>
menu.text.toLowerCase().includes(this.search.toLowerCase())
);
}
如何在两个级别上同时过滤?
编辑 1:
预期结果:
如果我是对的,你想检查它的 children 是否也不是空的?您可以使用 &&
filteredMenu() {
return this.menus.filter(menu =>
menu.children && menu.text.toLowerCase().includes(this.search.toLowerCase())
);
}
创建一个可以递归调用的函数。
methods: {
filterMenuItems(menuItems) {
return menuItems.filter(menuItem => {
let found = menuItem.text.toLowerCase().includes(this.search.toLowerCase());
if (!found && Array.isArray(menuItem.children)) {
found = this.filterMenuItems(menuItem.children);
}
return found;
});
}
}
现在你的计算 属性 可以 return this.filterMenuItems(this.menus)
filteredMenu() {
return this.filterMenuItems(this.menus);
}
这也允许无限的子级别
您可以使用 Destructuring assignment in order to get a value and set a predefined value, then using Some 您可以检查 Array
上的 truthy
条件。
所以换句话说,你需要做的是:
filteredMenu() {
return this.menus.filter(menu => {
// check if the parent has the value
const parentIncludesText = menu.text.toLowerCase().includes(this.search.toLowerCase())
// define a predefined value in case 'children' is null
const { children = [] } = menu || {}
// check if some of the childs has the value.
const childrenIncludesText = children.some(child => child.text.toLowerCase().includes(this.search.toLowerCase()))
// then return the result of the parent and the children.
return parentIncludesText || childrenIncludesText
});
}
您可以使用一个有用的函数 _isExist()
const _isExist = (menu, value) => menu.text.toLowerCase().includes(value.toLowerCase())
如果存在,您可以使用它在子数组中搜索
filteredMenu() {
return this.menus.filter(
menu =>
_isExist(menu, this.search) ||
(menu.children && menu.children.some(childMenu => _isExist(childMenu, this.search))),
)
}
我想你正在寻找这样的东西,它当然使用递归。不过,它使用递归的方式很重要,这意味着您要先探测 children ,然后确定是否存在 children(保留 parent), or 如果当前菜单项有给定的文本,它匹配。对于任何匹配的 children,您需要 parent,一直向内搜索菜单结构的每个分支,然后返回到 root-level 项。
这将调用 children 上的探测器,然后进一步向内运行整个过程,直到没有 children,返回每个向内的匹配集(并且它与 parent 项目),然后备份到下一个更高级别的工作。像这张图一样想,
1 match
2 match
3az < match
3ay < match
3ax < match
3a < [...match] match
3b < match
3 [...match] match
4a < match
4 [...match] match
5 match
另外,你不想过滤,你想减少到一个集合。
const search = (items, text) => {
const hasText = item => item.text.toLowerCase().includes(text.toLowerCase())
const probe = (found, item) => {
item.children = (item.children || []).reduce(probe, [])
if (item.children.length || hasText(item)) {
found.push(item)
}
return found
}
return items.reduce(probe, [])
}
... elsewhere ...
return search(this.menus, 'c')
https://jsfiddle.net/81wkh5df/6/
这个returns:
- 功能列表
- 职能部门
- 操作
- Cargar Pedidos