JQuery 根据组合的多个数据属性和搜索字段显示/隐藏多个元素
Posted
技术标签:
【中文标题】JQuery 根据组合的多个数据属性和搜索字段显示/隐藏多个元素【英文标题】:JQuery Show/Hide multiple elements based on combined multiple data attributes and search field 【发布时间】:2021-10-13 19:15:44 【问题描述】:我有一些像这样的 html 元素:
<div class="items">
<div class="item" data-opt1="val1" data-opt2="val2,val3">Item 1</div>
<div class="item" data-opt1="val4" data-opt2="val2,val5">Item 2</div>
<div class="item" data-opt1="val1" data-opt2="val3,val6">Item 3</div>
<div class="item" data-opt1="val7" data-opt2="val3,val5">Item 4</div>
</div>
和 2 个用作过滤器的变量、一个选项数组和一个搜索字符串,如下所示:
示例 1
var srcString = "val";
var filters = [
'opt1' : ['val1'],
'opt2' : ['val2','val6']
];
在这个例子中 item1 和 item3 应该是可见的,item2 和 item4 是不可见的。
示例 2
var srcString = "value";
var filters = [
'opt1' : ['val1'],
'opt2' : ['val2','val6']
];
所有项目都不应该是可见的,因为 var srcString 包含的词在任何数据属性中都不存在。
示例 3
var srcString = "val6";
var filters = [];
只有 item3 应该是可见的。
示例 4
var srcString = "";
var filters = [
'opt1' : ['val1','val7'],
'opt2' : ['val5']
];
只有 item4 应该是可见的,因为 item1 和 item3(即使有 opt1=val1)在 opt2 中没有 val5。
示例 5
var srcString = "";
var filters = [
'opt1' : ['val1','val7']
];
items: 1,3,4 应该是可见的。
我能够让所有这些过滤器一个一个地工作,但是当我尝试组合所有这些过滤器时就会出现问题。
搜索代码:
$(".item").each(function()
var item = $(this);
if (item.data('opt1').toLowerCase().indexOf(srcVal) >= 0
|| item.data('opt2').toLowerCase().indexOf(srcVal) >= 0)
item.removeClass('d-none');
else
item.addClass('d-none');
);
单个过滤器的代码:
var selectedOptions = filters['opt2'];
$(".item").each(function()
var item = $(this);
let _options = item.data('opt2') + '';
_options = _options.split(",");
let found = _options.some(r=> selectedOptions.includes(r));
if(found==true)
item.removeClass('d-none');
else
item.addClass('d-none');
)
感谢您的帮助
【问题讨论】:
我能够让所有这些过滤器一个一个地工作,但是当我尝试组合所有这些过滤器时会出现问题。 - 请包括这个尝试,它可能会更新您的尝试比从头开始更容易。 您可以将第二个的内容(不是每个本身,anon-func)放在第一个的if
中。
你能举个例子吗?我不明白你的意思.. 我希望代码能够适应,即使我将来必须添加更多属性来过滤.. if/else 是最好的方法?
@freedomn-m 我明白你的意思.. 但我的第二个每个循环都基于单个静态数组“selectedOptions”。要组合它们,我需要使用我的数组“过滤器”,其中 opt2 索引可以存在或不存在...
根据您的代码,您的场景“1”也应该显示 Item2,因为您使用了 .some
(又名“any”)并且“val2”匹配“val2”
【参考方案1】:
调整您现有的代码,您可以将第二个检查移动到第一个检查的通过内。
需要进行一些额外的检查,例如检查 .opt2
是否存在并具有值,但这些都是简单的检查。
$(".item").each(function()
var item = $(this);
if (item.data('opt1').toLowerCase().indexOf(srcString) >= 0 ||
item.data('opt2').toLowerCase().indexOf(srcString) >= 0)
item.removeClass('d-none');
var selectedOptions = filters['opt2'];
if (selectedOptions != null)
let _options = item.data('opt2') + '';
_options = _options.split(",");
if (_options.length > 0)
let found = _options.some(r => selectedOptions.includes(r));
if (found == true)
item.removeClass('d-none');
else
item.addClass('d-none');
else
item.addClass('d-none');
);
小提琴:https://jsfiddle.net/7t26n3pj/
注意:这使用提供的 OP 代码,因此与他们的示例不完全匹配,因为缺少对 opt1
的检查
您可以删除 if (_available_) continue
以减少代码缩进,方法是将检查移动到单独的函数中,并为通过/不通过返回 true/false - 这也将允许您在未来添加新的过滤器。
function applyFilter(filter)
$(".item").each(function()
var item = $(this);
if (passesFilter(item, filter))
item.removeClass('d-none');
else
item.addClass('d-none');
)
function passesFilter(item, filter)
if (item.data('opt1').toLowerCase().indexOf(filter.srcString) < 0 &&
item.data('opt2').toLowerCase().indexOf(filter.srcString) < 0)
return false;
var selectedOptions = filter.filters['opt2'];
if (selectedOptions == null) return true;
let _options = item.data('opt2') + '';
_options = _options.split(",");
if (_options.length === 0) return true;
let found = _options.some(r => selectedOptions.includes(r));
return found;
// Examples
$("button").click(function()
var filter = $(this).data("filter");
console.log(filter);
applyFilter(filter);
);
.d-none display:none;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="items">
<div class="item" data-opt1="val1" data-opt2="val2,val3">Item 1</div>
<div class="item" data-opt1="val4" data-opt2="val2,val5">Item 2</div>
<div class="item" data-opt1="val1" data-opt2="val3,val6">Item 3</div>
<div class="item" data-opt1="val7" data-opt2="val3,val5">Item 4</div>
</div>
<button type='button' data-filter='"srcString":"val","filters":"opt1":["val1"],"opt2":["val2","val6"]'>
test 1
</button>
<button type='button' data-filter='"srcString":"value","filters":"opt1":["val1"],"opt2":["val2","val6"]'>
test 2
</button>
<button type='button' data-filter='"srcString":"val6","filters":'>
test 3
</button>
<button type='button' data-filter='"srcString":"","filters":"opt1":["val1", "val7"],"opt2":["val5"]'>
test 4
</button>
<button type='button' data-filter='"srcString":"","filters":"opt1":["val1", "val7"]'>
test 5
</button>
【讨论】:
非常感谢您的帮助,但有些东西在方面不起作用。在测试 1 中,项目 2 不应该是可见的,因为过滤器 opt1 的选定值只有 val1,并且 item2 有 opt1=val4,即使 opt2 匹配......这就像 sql 中的 OR,可能我需要类似 AND 如前所述,它使用您的原始代码,该代码也选择了 item2 - 这是_options.some(r => selectedOptions.includes(r))
行,它指出至少需要匹配一个,而不是全部。您可能想将.some
更改为.every
是的,每个属性我至少需要一个(如果选择的话)。用 .every 改变 .some 不是解决方案以上是关于JQuery 根据组合的多个数据属性和搜索字段显示/隐藏多个元素的主要内容,如果未能解决你的问题,请参考以下文章