
Müssen Sie häufig Filterhandler für Ihre Daten schreiben? Es können Arrays zum Zeichnen von Tabellen, Karten, Listen sein - alles.
Wenn die Filterung statisch ist, ist alles einfach. Standardfunktionen map
, filter
und reduce
ganz ausreichend. Was aber, wenn die Daten eine komplexe Struktur oder Verschachtelung haben und es viele Regeln für den Filter geben kann? Regeln können wiederholt werden, Daten können geändert werden und je mehr Filtersteuerelemente angezeigt werden, desto komplexer und instabiler wird der Handlercode.
Wie kann das Problem der zunehmenden Komplexität gelöst werden?
Ich selbst war mit diesem Problem konfrontiert, als ich eine Anwendung entwickelte, die mit einer großen Datenmenge arbeitet. Allmählich wurden immer mehr neue Filter hinzugefügt.
, . . , . , . - .
, .
, :
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 . .

, . .
, .