
Apakah Anda sering harus menulis penangan filter untuk data Anda? Ini bisa berupa array untuk menggambar tabel, kartu, daftar - apa saja.
Ketika penyaringan bersifat statis, maka semuanya sederhana. Fitur standar map
, filter
dan reduce
cukup cukup. Tetapi bagaimana jika data memiliki struktur yang kompleks atau bersarang, dan mungkin ada banyak aturan untuk filter. Aturan dapat diulang, data dapat diubah, dan semakin banyak kontrol filter muncul, semakin kompleks dan tidak stabil kode handler akan.
Bagaimana mengatasi masalah meningkatnya kompleksitas?
Saya sendiri menghadapi masalah ini saat mengembangkan aplikasi yang bekerja dengan sejumlah besar data. Secara bertahap ditambahkan semakin banyak filter baru.
, . . , . , . - .
, .
, :
ng-table
โ . .List.js
โ ng-table, .filter.js
โ , , .Isotope
โ DOM . .
, :
- .
- .
- .
- ,
and
or
. - . .
- ( , , , , , )
awesome-data-filter.
, , .
.
npm install awesome-data-filter
.
, :
const users = [
{
age: 31,
name: "Marina Gilmore",
},
{
age: 34,
name: "Joyner Mccray",
},
{
age: 23,
name: "Inez Copeland",
},
{
age: 23,
name: "Marina Mitchell",
},
{
age: 25,
name: "Prince Spears",
},
];
:
const filterValue = {
age: 23,
searchText: "mari",
};
, .
:
matchText
โ ;equalProp
โ ;
betweenDates
โ ;equalOneOf
โ ;someInArray
โ ;isEmptyArray
โ ;lessThen
โ , ;moreThen
โ , ;not
โ .
matchText
equalProp
.
:
filterField
โ ;elementField
โ .
import {
buildFilter,
elementField,
filterField,
} from "awsome-data-filter";
import { matchText, equalProp } from "awsome-data-filter/rules";
import { and } from "awsome-data-filter/conditions";
const filter = buildFilter({
rules: {
elementFilter: and([
matchText(filterField("searchText"), elementField("name")),
equalProp(filterField("age"), elementField("age")),
]),
},
});
const { elements } = filter(
filterValue,
{
groups: [],
elements: users,
},
);
console.log(elements);
filter
groups
elements
.
, . .

, , elements
.
and
or
, 2 .
import {
buildFilter,
elementField,
filterField,
} from "awsome-data-filter";
import { matchText, equalProp } from "awsome-data-filter/rules";
import { or } from "awsome-data-filter/conditions";
const filter = buildFilter({
rules: {
elementFilter: or([
matchText(filterField("searchText"), elementField("name")),
equalProp(filterField("age"), elementField("age")),
]),
},
});
const { elements } = filter(
filterValue,
{
groups: [],
elements: users,
},
);
console.log(elements);
filterField
, elementField
.
constValue
.
or(..., matchText, [and([..., matchText, ...]), or([..., ...])])
. :
const dataList = [
{
groupName: "first group",
list: [
{ age: 31, name: "Marina" },
{ age: 23, name: "Fabio" },
],
},
{
groupName: "second group",
groups: [
{
groupName: "third group",
list: [],
groups: [
{
groupName: "fourth group",
list: [{ age: 42, name: "Li" }],
},
],
},
],
list: [
{ age: 41, name: "Marina" },
{ age: 29, name: "Inez" },
{ age: 33, name: "Marina" },
],
},
{
groupName: "fifth group",
list: [
{ age: 21, name: "Dmitriy" },
{ age: 22, name: "Li" },
{ age: 45, name: "Mitchell" },
],
},
];
traversal
:
import {
buildFilter,
elementField,
filterField,
} from "awsome-data-filter";
import { matchText } from "awsome-data-filter/rules";
const filter = buildFilter({
traversal: {
getChildrenFunc: group => group.list,
setChildrenFunc: (group, list) => ({ ...group, list }),
getGroupsFunc: group => group.groups,
setGroupsFunc: (group, groups) => ({ ...group, groups }),
},
rules: {
elementFilter: matchText(filterField("searchText"), elementField("name")),
},
});
const filterValue = {
searchText: "li",
};
const { groups } = filter(filterValue, {
groups: dataList,
elements: [],
});
console.log(groups);
elementFilter
, . groupFilter
.
import {
buildFilter,
elementField,
filterField,
} from "awsome-data-filter";
import { matchText } from "awsome-data-filter/rules";
const filter = buildFilter({
traversal: {
getChildrenFunc: group => group.list,
setChildrenFunc: (group, list) => ({ ...group, list }),
getGroupsFunc: group => group.groups,
setGroupsFunc: (group, groups) => ({ ...group, groups }),
},
rules: {
elementFilter: matchText(filterField("searchText"), elementField("name")),
groupFilter: matchText(filterField("groupName"), elementField("groupName")),
},
});
const filterValue = {
searchText: "li",
groupName: "fi",
};
const { groups } = filter(filterValue, {
groups: dataList,
elements: [],
});
console.log(groups);
first group
, , , .
fifth group
, , .
. :
const standardStrategy: StrategiesFilterInterface = {
elementHandler: ({
element,
tools: {
isGroupFilterIsActive,
applyElementFilter
},
}) => {
if (isGroupFilterIsActive) return null;
if (!applyElementFilter) return element;
return applyElementFilter(element, true) ? element : null;
},
groupHandler: ({
element: group,
originalElement: originalGroup,
tools: {
isGroupFilterIsActive,
applyElementFilter,
getIsGroupFilterHaveMatch,
getGroupsFunc,
getChildrenFunc,
setChildrenFunc,
},
}) => {
let newChildren = [];
let originalChildren = [];
const children = getChildrenFunc(group);
const childrenExists = !!children;
if (children) {
originalChildren = [...children];
newChildren = originalChildren.filter(element =>
applyElementFilter
? applyElementFilter(element, !isGroupFilterIsActive)
: !isGroupFilterIsActive,
);
}
if (!newChildren.length && getIsGroupFilterHaveMatch(group)) {
return originalGroup;
}
if (childrenExists) {
group = setChildrenFunc(group, newChildren);
}
const newGroups = getGroupsFunc(group);
const isGroupsExists = !!(newGroups && newGroups.length);
const isElementExists = !!(newChildren && newChildren.length);
return isElementExists || isGroupsExists ? group : null;
},
};
, filterStrategy
.
awesome-data-filter . .

, . .
, .