我有一个苗条的页面来显示帖子列表,我需要让用户能够根据几个条件筛选列表,例如:年份、标签、类别等.所有这些条件都应该是并发的,就像亚马逊网站的边栏一样.

使用派生存储时,我得到了一个运行良好的过滤器,但仍然无法同时应用2或3个过滤器.

对于"年"过滤器,我有以下代码:

import { readable, writable, derived } from "svelte/store";

export let data;
let posts = readable(data.posts);

const extractColumn = (arr, column) => arr.map((x) => x[column]);
const allYears = extractColumn(data.posts, "year");
const years = readable ([...new Set(allYears)]);
const filter = writable({ year: null });

const filteredPosts = derived([filter, posts], ([$filter, $posts]) => {
        if (!$filter.year) return $posts;
        return $posts.filter((x) => x.year === $filter.year);
    });

因此,根据帖子列表,我可以得到过滤器的年份数组,然后通过简单的 Select 触发过滤操作,这项工作非常好.

<select bind:value={$filter.year}>
    {#each $years as year}
        <option value={year}>{year}</option>
    {/each}
</select>

正如我在一开始所说的,重点是如何增加这个场景的复杂性,将一个简单的过滤器变成一个系统,并具有数量可变的动态累积过滤器.

谢谢你的建议.

推荐答案

为了使其更通用,我将从"自动"生成过滤器选项开始

    const filterOptions = derived(posts, $posts => {

        // set the columns you'd like to have a filter for
        const columns = ['year', 'language']
        //  const columns = Object.keys($posts[0]) // or change to this to have a filter for every property

        return columns.reduce((filterOptions, column) => {
            filterOptions[column] = extractUniqueColumnValues($posts, column)
            return filterOptions
        }, {})
    })

    function extractUniqueColumnValues (arr, column) {
        return Array.from(new Set(arr.map((x) => x[column])))
    } 

然后像这样展示

{#each Object.entries($filterOptions) as [column, values]}
{column}
<select bind:value={$filter[column]}>
    <option value={null} ></option>
    {#each values as value}
    <option value={value}>{value}</option>
    {/each}
</select>
{/each}

filter只可能是

const filter = writable({});

(It is initially set to {year: null, language: null} via the select value bindings)

One way to filter the posts could be this (or using reduce like Stephane Vanraes` answer is showing)

const filteredPosts = derived([filter, posts], ([$filter, $posts]) => {
        Object.entries($filter).forEach(([key, value]) => {
            if(value !== null) $posts = $posts.filter(x => x[key] == value)
        })      
        return $posts
    });

这是在这个基础上建立的REPL

Javascript相关问答推荐

配置WebAssembly/Emscripten本地生成问题

如何从调整大小/zoom 的SVG路径定义新的d属性?""

手机上的渲染错误文本必须在文本组件中渲染,但在浏览器上没有问题<><>

还原器未正确更新状态

在运行时使用Next JS App Router在服务器组件中运行自定义函数

400 bad request error posting through node-fetch

NG/Express API路由处理程序停止工作

如何在JAVASCRIPT中合并两组对象并返回一些键

WebSocketException:远程方在未完成关闭握手的情况下关闭了WebSocket连接.&#三十九岁;

在SuperBase JS客户端中寻址JSON数据

如何在下一个js中更改每个标记APEXCHARTS图表的 colored颜色

需要RTK-在ReactJS中查询多个组件的Mutations 数据

需要刷新以查看Mern堆栈应用程序中的更改

暂停后只有一次旋转JS

Html/JS:如何在脚本执行前阻止呈现?

获取S点击的元素类(这?)并将其应用于另一个元素(目标),同时删除目标元素上的所有类

如何使用JavaScript将动态表上具有相同值的行与某些条件合并

Chart.js折线图动态更改其y轴

UseEffectreact 18-花很长时间进行API调用

根据Vue 3中的父项宽度将props 值传递给子项