如何使用动态过滤器过滤 svelte 商店
How to filter a svelte store using a dynamic filter
我有一个派生商店,它必须使用 HTML 选择过滤器来过滤条目对象。现在我引入了一个额外的过滤器存储(可观察的)以在过滤器存储更改时强制派生存储回调到 运行。
但是filter变化的时候是否可以在没有filter store的情况下在下面的derived store中触发回调呢?我这里需要这个额外的商店吗?
下面的代码工作正常。我很好奇。
import { writable, derived } from 'svelte/store';
import { entries } from './../stores/entries.js';
export const filter = writable({
// to update filter use: $filter.kind = ...
// or: filter.update(o => Object.assign(o, {kind: .., batchId: ...}));
batchId: 'all',
kind: 'all',
});
let list, total;
export const view = derived(
[filter, entries],
([$filter, $entries], set) => {
total = 0;
if ($entries) {
// filter by HTML selects: kind, batchId
list = Object.keys($entries.map).sort().reduce((a, key) => {
if ((['all', $entries.map[key].description.kind].includes($filter.kind))
&& (['all', $entries.map[key].parentId].includes($filter.batchId))) {
total += $entries.map[key].grossValue;
a.push($entries.map[key]);
};
return a;
}, []);
set({list, total});
};
return () => {
set(null);
};
}, null
);
更新:使用自定义存储的伪派生可写
import { writable, derived } from 'svelte/store';
import { entries } from './../stores/entries.js';
let list, total;
const filter = writable({batchId: 'all', kind: 'all'});
export const view = () => {
const viewDerived = derived([filter, entries],
([$filter, $entries]) => {
total = 0;
if ($entries) {
// filter by HTML selects: kind, batchId
list = Object.keys($entries.map).sort().reduce((a, key) => {
if ((['all', $entries.map[key].description.kind].includes($filter.kind))
&& (['all', $entries.map[key].parentId].includes($filter.batchId))) {
total += $entries.map[key].grossValue;
a.push($entries.map[key]);
};
return a;
}, []);
return {list, total};
} else return null;
}
);
// custom store methods
return {
subscribe: viewDerived.subscribe,
set: filter.set,
update: (obj) => filter.update(o => Object.assign(o, obj)),
reset: () => filter.set({batchId: 'all', kind: 'all'}),
};
}();
您可以将派生存储中的逻辑提取到您自己控制的函数/对象中,使用 API 手动触发更新...但这不是一个好主意。那会破坏一些封装而没有任何好处。
您的 writable
+ derived
解决方案是,IMO,最直接和优雅的解决方案。它明确地概述了数据依赖关系,并清晰地分离了关注点,不涉及神秘的代码。它还为 Svelte 提供监控更改所需的功能,并以最精细的粒度自动为您管理订阅。
这是一个不错的模式,非常适合您的用例。我会保持这样。
我有一个派生商店,它必须使用 HTML 选择过滤器来过滤条目对象。现在我引入了一个额外的过滤器存储(可观察的)以在过滤器存储更改时强制派生存储回调到 运行。
但是filter变化的时候是否可以在没有filter store的情况下在下面的derived store中触发回调呢?我这里需要这个额外的商店吗? 下面的代码工作正常。我很好奇。
import { writable, derived } from 'svelte/store';
import { entries } from './../stores/entries.js';
export const filter = writable({
// to update filter use: $filter.kind = ...
// or: filter.update(o => Object.assign(o, {kind: .., batchId: ...}));
batchId: 'all',
kind: 'all',
});
let list, total;
export const view = derived(
[filter, entries],
([$filter, $entries], set) => {
total = 0;
if ($entries) {
// filter by HTML selects: kind, batchId
list = Object.keys($entries.map).sort().reduce((a, key) => {
if ((['all', $entries.map[key].description.kind].includes($filter.kind))
&& (['all', $entries.map[key].parentId].includes($filter.batchId))) {
total += $entries.map[key].grossValue;
a.push($entries.map[key]);
};
return a;
}, []);
set({list, total});
};
return () => {
set(null);
};
}, null
);
更新:使用自定义存储的伪派生可写
import { writable, derived } from 'svelte/store';
import { entries } from './../stores/entries.js';
let list, total;
const filter = writable({batchId: 'all', kind: 'all'});
export const view = () => {
const viewDerived = derived([filter, entries],
([$filter, $entries]) => {
total = 0;
if ($entries) {
// filter by HTML selects: kind, batchId
list = Object.keys($entries.map).sort().reduce((a, key) => {
if ((['all', $entries.map[key].description.kind].includes($filter.kind))
&& (['all', $entries.map[key].parentId].includes($filter.batchId))) {
total += $entries.map[key].grossValue;
a.push($entries.map[key]);
};
return a;
}, []);
return {list, total};
} else return null;
}
);
// custom store methods
return {
subscribe: viewDerived.subscribe,
set: filter.set,
update: (obj) => filter.update(o => Object.assign(o, obj)),
reset: () => filter.set({batchId: 'all', kind: 'all'}),
};
}();
您可以将派生存储中的逻辑提取到您自己控制的函数/对象中,使用 API 手动触发更新...但这不是一个好主意。那会破坏一些封装而没有任何好处。
您的 writable
+ derived
解决方案是,IMO,最直接和优雅的解决方案。它明确地概述了数据依赖关系,并清晰地分离了关注点,不涉及神秘的代码。它还为 Svelte 提供监控更改所需的功能,并以最精细的粒度自动为您管理订阅。
这是一个不错的模式,非常适合您的用例。我会保持这样。