我有一系列物品,我想根据它们的大小,颜色和衣领过滤它们。
每当我取消选中一个复选框时,一切都按预期工作,但当我再次重新检查它时,它会带回不需要的对象。
var DATABASE = [
{id:0o1, size: "XL", color:"red", collar: "v-neck"},
{id:0o2, size: "S", color:"blue", collar: "regular"},
{id:0o3, size: "XXL", color:"red", collar: "scoop"},
{id:0o4, size: "L", color:"green", collar: "v-neck"},
{id:0o5, size: "XL", color:"blue", collar: "turtle-neck"},
{id:0o6, size: "L", color:"red", collar: "v-neck"}
];
window.onload = function () {
var vNeckCollarCheckbox = document.querySelector('#vneck-collar-checkbox');
var xlSizeCheckbox = document.querySelector('#xl-size-checkbox');
var redColorCheckbox = document.querySelector('#red-color-checkbox');
var div = document.querySelector('div');
var DB = DATABASE;
function filterByVneckCollar() {
let vNeckCollar = DATABASE.filter(function (item) {
return item.collar === "v-neck";
});
if(!vNeckCollarCheckbox.checked){
DB = DB.filter(function (i) {
return vNeckCollar.indexOf(i) < 0;
});
div.innerHTML = JSON.stringify(DB);
}
else{
DB = DB.concat(vNeckCollar);
div.innerHTML = JSON.stringify(DB);
}
}
function filterByXlSize() {
let xlSize = DATABASE.filter(function (item) {
return item.size === "XL";
});
if(!xlSizeCheckbox.checked){
DB = DB.filter(function (i) {
return xlSize.indexOf(i) < 0;
});
div.innerHTML = JSON.stringify(DB);
}
else{
DB = DB.concat(xlSize);
div.innerHTML = JSON.stringify(DB);
}
}
function filterByRedColor() {
let redColor = DATABASE.filter(function (item) {
return item.color === "red";
});
if(!redColorCheckbox.checked){
DB = DB.filter(function (i) {
return redColor.indexOf(i) < 0;
});
div.innerHTML = JSON.stringify(DB);
}
else{
DB = DB.concat(redColor);
div.innerHTML = JSON.stringify(DB);
}
}
div.innerHTML = JSON.stringify(DB);
vNeckCollarCheckbox.addEventListener('change', filterByVneckCollar);
xlSizeCheckbox.addEventListener('change', filterByXlSize);
redColorCheckbox.addEventListener('change', filterByRedColor);
};
&#13;
<html>
<head>
<script src="js.js"></script>
</head>
<body>
<form action="#">
<input type="checkbox" id="vneck-collar-checkbox" checked>
<label for="vneck-collar-checkbox">V-neck collar</label>
<br>
<input type="checkbox" id="xl-size-checkbox" checked>
<label for="xl-size-checkbox">XL size</label>
<br>
<input type="checkbox" id="red-color-checkbox" checked>
<label for="red-color-checkbox">Red color</label>
</form>
<div></div>
</body>
</html>
&#13;
试试这个:
你会看到包含&#34;颜色的对象:红色&#34;出现。
我知道问题出现在 DB = DB.concat(xxxxx); of else {}声明中,但我不知道如何实现所需的输出。
赞赏实现此类过滤器的任何其他解决方案/概念。
答案 0 :(得分:2)
只需使用您需要的规则组合过滤DATABASE
一次。
我已经为你提供了一个更复杂的功能JSDoc,我制作了通用的,所以也可以用于其他的东西
/**
* @callback FilterRuleTest
* @param {Object} obj The target Object
* @returns {Boolean} Whether obj passed the test
*/
/**
* @typedef {Object} FilterRule
* @property {String} [key] A property key to find on the target
* @property {String} [value] The value assigned to the key of the target
* @property {FilterRuleTest} [test] A function to run on target, return bool
*/
/** Filters an Array of Objects
* @param {[Object]} arrayOfObjects The Array of Objects to filter
* @param {[FilterRule]} arrayOfRules The Array of Objects to filter with
* @param {Boolean} [invert] Return the opposite of the rules
* @param {Boolean} [emptyRulePasses] Default behaviour of empty rule
* @returns {[Object]} The filtered result
*/
function objFilter(arrayOfObjects, arrayOfRules, invert = false, emptyRulePasses = false) {
return arrayOfObjects.filter(obj => {
return invert !== arrayOfRules.every(rule => {
if ('key' in rule) {
if ('value' in rule)
return obj[rule.key] === obj[rule.value];
return rule.key in obj;
}
if ('test' in rule) {
return rule.test(obj);
}
return emptyRulePasses;
});
});
}
function createFilterRules(collar, size, color) {
let rules = [];
if (collar) rules.push({key: 'collar', value: collar});
if (size) rules.push({key: 'size', value: size});
if (color) rules.push({key: 'color', value: color});
return rules;
}
const vNeckCollarCheckbox = document.querySelector('#vneck-collar-checkbox');
const xlSizeCheckbox = document.querySelector('#xl-size-checkbox');
const redColorCheckbox = document.querySelector('#red-color-checkbox');
const div = document.querySelector('div');
function filterClothes(db) {
return objFilter(
db,
createFilterRules(
vNeckCollarCheckbox.checked ? 'v-neck' : null,
xlSizeCheckbox.checked ? 'XL' : null,
redColorCheckbox.checked ? 'red' : null
)
);
}
function clothesHandle() {
div.innerHTML = JSON.stringify(filterClothes(DATABASE));
}
vNeckCollarCheckbox.addEventListener('change', clothesHandle);
xlSizeCheckbox.addEventListener('change', clothesHandle);
redColorCheckbox.addEventListener('change', clothesHandle);
答案 1 :(得分:2)
问题是您的过滤器功能以完整集开始,并仅基于其中一个复选框值过滤掉。
而是创建一个一对一的过滤器。
您还可以以简洁的方式编写过滤条件:设置复选框,或者应用条件。这可以用布尔||
运算符表示。
最后,我建议使用DOMContentLoaded
事件而不是load
事件,因为它会更快地触发,同时仍保证可以访问DOM元素。
var DATABASE = [
{id:0o1, size: "XL", color:"red", collar: "v-neck"},
{id:0o2, size: "S", color:"blue", collar: "regular"},
{id:0o3, size: "XXL", color:"red", collar: "scoop"},
{id:0o4, size: "L", color:"green", collar: "v-neck"},
{id:0o5, size: "XL", color:"blue", collar: "turtle-neck"},
{id:0o6, size: "L", color:"red", collar: "v-neck"}
];
document.addEventListener("DOMContentLoaded", function () {
var vNeckCollarCheckbox = document.querySelector('#vneck-collar-checkbox');
var xlSizeCheckbox = document.querySelector('#xl-size-checkbox');
var redColorCheckbox = document.querySelector('#red-color-checkbox');
var div = document.querySelector('div');
function applyFilter() {
div.innerHTML = JSON.stringify(DATABASE.filter(function (item) {
return (vNeckCollarCheckbox.checked || item.collar !== "v-neck") &&
(xlSizeCheckbox.checked || item.size !== "XL") &&
(redColorCheckbox.checked || item.color !== "red");
}));
}
vNeckCollarCheckbox.addEventListener('change', applyFilter);
xlSizeCheckbox.addEventListener('change', applyFilter);
redColorCheckbox.addEventListener('change', applyFilter);
applyFilter();
});
<form action="#">
<input type="checkbox" id="vneck-collar-checkbox" checked>
<label for="vneck-collar-checkbox">V-neck collar</label>
<br>
<input type="checkbox" id="xl-size-checkbox" checked>
<label for="xl-size-checkbox">XL size</label>
<br>
<input type="checkbox" id="red-color-checkbox" checked>
<label for="red-color-checkbox">Red color</label>
</form>
<div></div>
答案 2 :(得分:1)
您的复选框每个都会为全局过滤器提供单独的部分。如果取消选中复选框,1。您的全局过滤器将被修改,2。您选择的数据是使用修改后的过滤器过滤数据库的结果。
关于您的全球&#39; filter:您可以将它实现为单个Array.filter()回调,如果应该根据任何复选框过滤给定元素,则返回true,或者您可以将调用链接到Array.filter()根据单个复选框的回调过滤元素。
不需要连接。
答案 3 :(得分:1)
每当其中一个过滤器发生更改时,您可以按所有属性过滤基础数组。
function applyFilters(){
curr_db = DB;
if ( ! vNeckCollarCheckbox.checked) {
curr_db = filterByVneckCollar(curr_db);
}
if ( ! xlSizeCheckbox.checked) {
curr_db = filterByXlSize(curr_db);
}
if ( ! redColorCheckbox.checked) {
curr_db = filterByRedColor(curr_db);
}
div.innerHTML = JSON.stringify(curr_db);
}
vNeckCollarCheckbox.addEventListener('change', applyFilters);
xlSizeCheckbox.addEventListener('change', applyFilters);
redColorCheckbox.addEventListener('change', applyFilters);
然后使用过滤器功能仅删除不需要的项目。
function filterByRedColor(curr_db) {
return curr_db.filter(function(){
return item.color != "red";
});
}
...
答案 4 :(得分:1)
只需一个过滤器功能就可以解决这个问题,每当你逐项过滤检查你的过滤器是否满足复选框的每个条件时......如果是,那么通过在过滤器函数中返回true来接受它。 。否则为该项目返回false将不会在选择数据库中显示该项目......我希望这可以澄清您的疑问......
var selection = [];
var vNeckCollarCheckbox = document.querySelector('#vneck-collar-checkbox').checked;
var xlSizeCheckbox = document.querySelector('#xl-size-checkbox').checked;
var redColorCheckbox = document.querySelector('#red-color-checkbox').checked;
selection = DATABASE.filter(function (item) {
// Write all condition which will fail for the current data here and return false, every condition passes it will send true by default at the end
if(vNeckCollarCheckbox) {
if(item.collar != "v-neck") {
return false;
}
}
if(xlSizeCheckbox) {
if(item.size != "XL") {
return false;
}
}
if(redColorCheckbox) {
if(item.color != "red") {
return false;
}
}
return true;
});