基于JavaScript實(shí)現(xiàn)前端數(shù)據(jù)多條件篩選功能
有時候也會需要在前端進(jìn)行數(shù)據(jù)篩選,增強(qiáng)交互體驗(yàn)。當(dāng)數(shù)據(jù)可用的篩選條件較多時,把邏輯寫死會給后期維護(hù)帶來很大麻煩。下面是我自己寫的一個簡單的篩選器,篩選條件可以根據(jù)數(shù)據(jù)包含的字段動態(tài)設(shè)置。
仿照京東的篩選條件,這里就取價(jià)格區(qū)間和品牌作為測試。
代碼
代碼中主要使用js的過濾器Array.prototype.filter,該方法會對數(shù)組元素進(jìn)行遍歷檢查,返回一個符合檢查條件的新數(shù)組,不會改變原數(shù)組。
// 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]
有了這個方法,篩選數(shù)據(jù)方便了很多,下面先定義一個商品類。
// 定義商品類 function Product(name, brand, price) { this.name = name; // 名稱 this.brand = brand; // 品牌 this.price = price; // 價(jià)格 }
創(chuàng)建一個過濾器對象,把所有過濾數(shù)據(jù)的方法放在里面。為了能自動適配不同的篩選條件,將篩選條件分為兩個大類,一個是區(qū)間類型rangesFilter ,如:品牌、內(nèi)存等;一個是選擇類型choosesFilter,如:價(jià)格、屏幕尺寸等。
不同大類同時篩選時,進(jìn)行的是與邏輯,每個大類在上一個大類篩選結(jié)果上進(jìn)行篩選。比如我要篩選2000-5000塊的華為手機(jī),先調(diào)用rangesFilter篩選products并返回結(jié)果result1,然后用choosesFilter篩選result1并返回結(jié)果resulte2。
當(dāng)然,如果還有其它大類,不一定是與邏輯,再另行處理。
// 商品篩選器 const ProductFilters = { /** * 區(qū)間類型篩選 * @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) { } }
區(qū)間類型的篩選,代碼如下。
// 區(qū)間類型條件結(jié)構(gòu) 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 { /** * 循環(huán)多個區(qū)間條件, * 每種區(qū)間類型應(yīng)該只有一個, * 比如價(jià)格區(qū)間不會有1000-2000和4000-6000同時需要的情況 */ for (let range of ranges) { // 多個不同類型區(qū)間是與邏輯,可以直接賦值給自身 products = products.filter(function (item) { return item[range.type] >= range.low && item[range.type] <= range.high; }); } return products; } }
選擇類型篩選:
// 選擇類型條件結(jié)構(gòu) 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 { /** * 選擇類型條件是或邏輯,使用數(shù)組連接concat */ for (let choice of chooses) { tmpProducts = tmpProducts.concat(products.filter(function (item) { return item[choice.type].indexOf(choice.value) !== -1; })); } } return tmpProducts; }
定義一個執(zhí)行函數(shù)doFilter()。
function doFilter(products, conditions) { // 根據(jù)條件循環(huán)調(diào)用篩選器里的方法 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: '華為' } ] }
測試
創(chuàng)建10個商品數(shù)據(jù),以及篩選條件
// 商品數(shù)組 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: '蘋果' } ] }
調(diào)用函數(shù)
let result = doFilter(products, Conditions); console.log(result);
輸出
代碼的擴(kuò)展性和可維護(hù)性都很好,只要保證篩選條件中的type字段在商品數(shù)據(jù)中一致都可以篩選,比如將篩選條件改為
let Conditions = { ranges: [ { type: 'price', low: 3000, high: 6000 } ], chooses: [ { type: 'name', value: 'iPhone' } ] }
輸出
搜索匹配等一些地方也需要優(yōu)化,是否區(qū)分大小寫、是完全匹配還是模糊匹配等。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript實(shí)現(xiàn)翻轉(zhuǎn)圖片的三種方法小結(jié)
有時,我們可能需要翻轉(zhuǎn)Web應(yīng)用中的媒體元素,所以這篇文章小編為大家詳細(xì)介紹了三種使用JavaScript翻轉(zhuǎn)圖片的方法,希望對大家有所幫助2024-01-01jQuery 實(shí)現(xiàn)倒計(jì)時天,時,分,秒功能
本文通過html代碼和js代碼給大家介紹了實(shí)現(xiàn)倒計(jì)時天,時,分,秒功能,非常不錯,具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-07-07js實(shí)現(xiàn)對table的增加行和刪除行的操作方法
下面小編就為大家?guī)硪黄猨s實(shí)現(xiàn)對table的增加行和刪除行的操作方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10JS綁定事件監(jiān)聽的幾種實(shí)現(xiàn)方法匯總
在JavaScript中事件監(jiān)聽是一種用于處理用戶交互的機(jī)制,下面這篇文章主要給大家介紹了關(guān)于JS綁定事件監(jiān)聽的幾種實(shí)現(xiàn)方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10