JS前端数据多条件筛选

作者: 月光下的圆珠笔 | 来源:发表于2017-09-27 15:35 被阅读200次

有时候也会需要在前端进行数据筛选,增强交互体验。当数据可用的筛选条件较多时,把逻辑写死会给后期维护带来很大麻烦。下面是我自己写的一个简单的筛选器,筛选条件可以根据数据包含的字段动态设置。

仿照京东的筛选条件,这里就取价格区间和品牌作为测试。

代码

代码中主要使用js的过滤器Array.prototype.filter,该方法会对数组元素进行遍历检查,返回一个符合检查条件的新数组,不会改变原数组。

// filter()
var foo = [0,1,2,3,4,5,6,7,8,9];

var foo1 = foo.filter(
    function(item) {
        return item >= 5
    }
);

console.log(foo1);  // [5, 6, 7, 8, 9]

有了这个方法,筛选数据方便了很多,下面先定义一个商品类。

// 定义商品类
function Product(name, brand, price) {
    this.name = name;  // 名称
    this.brand = brand;   // 品牌
    this.price = price;  // 价格
}

创建一个过滤器对象,把所有过滤数据的方法放在里面。为了能自动适配不同的筛选条件,将筛选条件分为两个大类,一个是区间类型rangesFilter ,如:品牌、内存等;一个是选择类型choosesFilter,如:价格、屏幕尺寸等。

不同大类同时筛选时,进行的是与逻辑,每个大类在上一个大类筛选结果上进行筛选。比如我要筛选2000-5000块的华为手机,先调用rangesFilter筛选products并返回结果result1,然后用choosesFilter筛选result1并返回结果resulte2

当然,如果还有其它大类,不一定是与逻辑,再另行处理。

// 商品筛选器
const ProductFilters = {
    /**
     * 区间类型筛选
     * @param {array<Product>} products
     * @param {array<{type: String, low: number, high: number}>} ranges
     */
    rangesFilter: function (products, ranges) { } 

    /**
     * 选择类型筛选
     * @param {array<Product>} products
     * @param {array<{type: String, value: String}>} chooses
     */
    choosesFilter: function (products, chooses) { }
}

区间类型的筛选,代码如下。

// 区间类型条件结构
ranges: [
        {
            type: 'price',  // 筛选类型/字段
            low: 3000,  // 最小值
            high: 6000  // 最大值
        }
    ]
/**
     * @param {array<Product>} products
     * @param {array<{type: String, low: number, high: number}>} ranges
     */
    rangesFilter: function (products, ranges) {
        if (ranges.length === 0) {
            return products;
        } else {
            /**
             * 循环多个区间条件,
             * 每种区间类型应该只有一个,
             * 比如价格区间不会有1000-2000和4000-6000同时需要的情况
             */
            for (let range of ranges) {
                // 多个不同类型区间是与逻辑,可以直接赋值给自身
                products = products.filter(function (item) {
                    return item[range.type] >= range.low && item[range.type] <= range.high;
                });
            }
            return products;
        }
    }

选择类型筛选:

// 选择类型条件结构
chooses: [
        {
            type: 'brand',
            value: '华为'
        },
        {
            type: 'brand',
            value: '苹果'
        }
    ]
/**
     * @param {array<Product>} products
     * @param {array<{type: String, value: String}>} chooses
     */
    choosesFilter: function (products, chooses) {
        let tmpProducts = [];
        if (chooses.length === 0) {
            tmpProducts = products;
        } else {
            /**
             * 选择类型条件是或逻辑,使用数组连接concat
             */
            for (let choice of chooses) {
                tmpProducts = tmpProducts.concat(products.filter(function (item) {
                    return item[choice.type].indexOf(choice.value) !== -1;
                }));
            }
        }
        return tmpProducts;
    }

定义一个执行函数doFilter()

function doFilter(products, conditions) {
    // 根据条件循环调用筛选器里的方法
    for (key in conditions) {
        // 判断是否有需要的过滤方法
        if (ProductFilters.hasOwnProperty(key + 'Filter') && typeof ProductFilters[key + 'Filter'] === 'function') {
            products = ProductFilters[key + 'Filter'](products, Conditions[key]);
        }
    }
    return products;
}
// 将两种大类的筛选条件放在同一个对象里
let Conditions = {
    ranges: [
        {
            type: 'price',
            low: 3000,
            high: 6000
        }
    ],
    chooses: [
        {
            type: 'brand',
            value: '华为'
        }
    ]
}

测试

创建10个商品数据,以及筛选条件

// 商品数组
const products = [
    new Product('华为荣耀9', '华为', 2299),
    new Product('华为P10', '华为', 3488),
    new Product('小米MIX2', '小米', 3599),
    new Product('小米6', '小米', 2499),
    new Product('小米Note3', '小米', 2499),
    new Product('iPhone7 32G', '苹果', 4588),
    new Product('iPhone7 Plus 128G', '苹果', 6388),
    new Product('iPhone8', '苹果', 5888),
    new Product('三星Galaxy S8', '三星', 5688),
    new Product('三星Galaxy S7 edge', '三星', 3399),
];
// 筛选条件
let Conditions = {
    ranges: [
        {
            type: 'price',
            low: 3000,
            high: 6000
        }
    ],
    chooses: [
        {
            type: 'brand',
            value: '华为'
        },
        {
            type: 'brand',
            value: '苹果'
        }
    ]
}

调用函数

let result = doFilter(products, Conditions);
console.log(result);

输出

image.png

代码的扩展性和可维护性都很好,只要保证筛选条件中的type字段在商品数据中一致都可以筛选,比如将筛选条件改为

let Conditions = {
    ranges: [
        {
            type: 'price',
            low: 3000,
            high: 6000
        }
    ],
    chooses: [
        {
            type: 'name',
            value: 'iPhone'
        }
    ]
}

输出

image.png

搜索匹配等一些地方也需要优化,是否区分大小写、是完全匹配还是模糊匹配等。

相关文章

  • JS前端数据多条件筛选

    有时候也会需要在前端进行数据筛选,增强交互体验。当数据可用的筛选条件较多时,把逻辑写死会给后期维护带来很大麻烦。下...

  • js 前端数据多条件筛选过滤

    在实际项目中,我们需要根据筛选框中的条件来实现数据的过滤,下面为过滤方法: //@param condition ...

  • js按条件筛选数据

    1、filter() 返回符合筛选条件的所有元素 2、find() 返回符合测试条件的第一个数组元素值 3、so...

  • pandas学习笔记(一)

    if-then和if-then-else逻辑实现 筛选出某列满足条件的数据 筛选出多列满足条件的数据 切片用法 p...

  • vue elementUI 实现el-table 表头筛选,表头

    表头筛选、排序功能: 可以做前端筛选,排序,(存在问题,前端无法对所有数据进行筛选或者排序,只能对当页数据。 所以...

  • python之pandas数据筛选和csv操作

    1. 数据筛选 (1)单条件筛选 (2)多条件筛选 可以使用&(并)与| (或)操作符或者特定的函数实现多条件筛选...

  • pandas dataframe Boolean条件筛选数据2

    Boolean条件筛选数据2 复杂的条件筛选条件1:score>=8 并且 ans_name 是以Mike开头条件...

  • pandas dataframe boolean条件数据筛选3

    pandas dataframe boolean条件数据筛选3 列与列之间的比较形成的筛选条件筛选出 answer...

  • dplyr-filter行筛选

    数据集 利用filter进行行筛选 单个条件 filter单条件筛选,可以直接传入列名;传入表达式进行筛选;注意遇...

  • WPF 数据绑定(四)

    筛选的数据源的绑定,使用Linq Filter Data Collection。从数据集合中筛选符合设定条件的数据...

网友评论

    本文标题:JS前端数据多条件筛选

    本文链接:https://www.haomeiwen.com/subject/cwduextx.html