按数据属性数组过滤 jquery 个对象
Filtering jquery objects by data attribute array
是否有更简单、更好或更简洁的方法来过滤利用包含数组的数据属性的元素列表?
目前我们有一个很大的项目列表,每个项目都包含 1 个或多个标签,数组中存储在 "data-tags" 属性中,如下所示:
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":2,"name":"Tag 02"}]'></div>
<div class="viewItem" data-tags='[{"id":2,"name":"Tag 02"}]'></div>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":3,"name":"Tag 03"}]'></div>
目的是仅显示数据标签数组中具有特定标签的 div。以下代码有效,但我觉得在处理大量项目时效率很低,想找到更好的答案,无论是使用 jquery 过滤器还是 grep 或其他。
$(function () {
//Instantiate variables
var $viewItems = $('.viewItem');
var filterId = 2;
//Hide all items in object array.
$viewItems.hide();
//Loop thru EACH item and show only those with matching id in array
$viewItems.each(function () {
var thisItem = $(this);
var array = thisItem.data("tags");
$.each(array, function (i, obj) {
if (obj.id == filterId) { thisItem.show(); return false; }
});
});
});
您可以为每个标签创建 css classes。示例:tag-1、tag-2 等。
将标签放入 class 部分,如下所示:<div class="viewItem tag-1 tag2".../>
因此,您可以轻松 select/show/hide 任何标签组合,如下所示:
// Hide tag-1
$(".tag-1").css('display','none')
// Show tag-2
$(".tag-2").css('display','block');
// Select elements with tag-1 and tag-2
$(".tag-1 tag-2").css('background','pink');
使用jQuery grep
函数过滤您的元素。然后在 grep 函数中,解析 data-tags
属性并查找是否存在具有给定 id 的元素:
var filterId = 1;
var dataTags;
var arr = $.grep($('.viewItem'), function( el ) {
dataTags = JSON.parse($(el).attr('data-tags'));
return dataTags.find(el => el.id === filterId);
});
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":2,"name":"Tag 02"}]'></div>
<div class="viewItem" data-tags='[{"id":2,"name":"Tag 023"}]'></div>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":3,"name":"Tag 03"}]'></div>
首先,data
方法相当快:jQuery 仅在第一次访问时从 DOM 中读取值,但随后保留值(此中的对象case) 在内存中,并且不会再次读取 DOM 的数据属性。
因此,如果这些 JSON 值不是很大,按 id 过滤项目将不会是占用大部分时间的部分。最耗时的部分将是您调用 .hide()
和 .show()
的地方,因为它涉及与 DOM 和渲染的交互。
但是,如果你真的需要优化它,你可以通过这个 JSON id 值做一些预处理和键控你的元素,例如像这样:
$(function () {
// Pre-processing: key all viewItems by the id in their data-tags:
var hash = $('.viewItem').get().reduce(function (hash, div) {
return $(div).data("tags").reduce(function (hash, o) {
hash[o.id] = (hash[o.id] || []).concat(div);
return hash;
}, hash);
}, {});
// Actual filtering
$('#apply').click(function() {
var filterId = $('#filter').val();
$('.viewItem').hide();
$(hash[filterId]).show();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Filter ID: <input id="filter"><button id="apply">Apply</button><br>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":2,"name":"Tag 02"}]'>1,2</div>
<div class="viewItem" data-tags='[{"id":2,"name":"Tag 02"}]'>2</div>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":3,"name":"Tag 03"}]'>1,3</div>
势在必行
由于创建散列的 函数式 方法可能看起来令人困惑,我在这里提供 强制性 替代方法。但是生成的散列对象将完全相同:
$(function () {
// Pre-processing: key all viewItems by the id in their data-tags:
var hash = [];
$('.viewItem').each(function (i, div) {
$.each($(div).data("tags"), function (j, obj) {
if (!(obj.id in hash)) hash[obj.id] = [];
hash[obj.id].push(div);
});
});
// Actual filtering
$('#apply').click(function() {
var filterId = $('#filter').val();
$('.viewItem').hide();
$(hash[filterId]).show();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Filter ID: <input id="filter"><button id="apply">Apply</button><br>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":2,"name":"Tag 02"}]'>1,2</div>
<div class="viewItem" data-tags='[{"id":2,"name":"Tag 02"}]'>2</div>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":3,"name":"Tag 03"}]'>1,3</div>
jQuery 过滤器怎么样?
var $viewItems = $('.viewItem');
var filterId = 2;
//Hide all items in object array.
$viewItems.hide();
//Loop thru EACH item and show only those with matching id in array
$viewItems.filter(function (i, el) {
var dataTags = $(el).data("tags");
return dataTags.filter(tag => tag.id === filterId).length
}).show()
是否有更简单、更好或更简洁的方法来过滤利用包含数组的数据属性的元素列表?
目前我们有一个很大的项目列表,每个项目都包含 1 个或多个标签,数组中存储在 "data-tags" 属性中,如下所示:
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":2,"name":"Tag 02"}]'></div>
<div class="viewItem" data-tags='[{"id":2,"name":"Tag 02"}]'></div>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":3,"name":"Tag 03"}]'></div>
目的是仅显示数据标签数组中具有特定标签的 div。以下代码有效,但我觉得在处理大量项目时效率很低,想找到更好的答案,无论是使用 jquery 过滤器还是 grep 或其他。
$(function () {
//Instantiate variables
var $viewItems = $('.viewItem');
var filterId = 2;
//Hide all items in object array.
$viewItems.hide();
//Loop thru EACH item and show only those with matching id in array
$viewItems.each(function () {
var thisItem = $(this);
var array = thisItem.data("tags");
$.each(array, function (i, obj) {
if (obj.id == filterId) { thisItem.show(); return false; }
});
});
});
您可以为每个标签创建 css classes。示例:tag-1、tag-2 等。
将标签放入 class 部分,如下所示:<div class="viewItem tag-1 tag2".../>
因此,您可以轻松 select/show/hide 任何标签组合,如下所示:
// Hide tag-1
$(".tag-1").css('display','none')
// Show tag-2
$(".tag-2").css('display','block');
// Select elements with tag-1 and tag-2
$(".tag-1 tag-2").css('background','pink');
使用jQuery grep
函数过滤您的元素。然后在 grep 函数中,解析 data-tags
属性并查找是否存在具有给定 id 的元素:
var filterId = 1;
var dataTags;
var arr = $.grep($('.viewItem'), function( el ) {
dataTags = JSON.parse($(el).attr('data-tags'));
return dataTags.find(el => el.id === filterId);
});
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":2,"name":"Tag 02"}]'></div>
<div class="viewItem" data-tags='[{"id":2,"name":"Tag 023"}]'></div>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":3,"name":"Tag 03"}]'></div>
首先,data
方法相当快:jQuery 仅在第一次访问时从 DOM 中读取值,但随后保留值(此中的对象case) 在内存中,并且不会再次读取 DOM 的数据属性。
因此,如果这些 JSON 值不是很大,按 id 过滤项目将不会是占用大部分时间的部分。最耗时的部分将是您调用 .hide()
和 .show()
的地方,因为它涉及与 DOM 和渲染的交互。
但是,如果你真的需要优化它,你可以通过这个 JSON id 值做一些预处理和键控你的元素,例如像这样:
$(function () {
// Pre-processing: key all viewItems by the id in their data-tags:
var hash = $('.viewItem').get().reduce(function (hash, div) {
return $(div).data("tags").reduce(function (hash, o) {
hash[o.id] = (hash[o.id] || []).concat(div);
return hash;
}, hash);
}, {});
// Actual filtering
$('#apply').click(function() {
var filterId = $('#filter').val();
$('.viewItem').hide();
$(hash[filterId]).show();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Filter ID: <input id="filter"><button id="apply">Apply</button><br>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":2,"name":"Tag 02"}]'>1,2</div>
<div class="viewItem" data-tags='[{"id":2,"name":"Tag 02"}]'>2</div>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":3,"name":"Tag 03"}]'>1,3</div>
势在必行
由于创建散列的 函数式 方法可能看起来令人困惑,我在这里提供 强制性 替代方法。但是生成的散列对象将完全相同:
$(function () {
// Pre-processing: key all viewItems by the id in their data-tags:
var hash = [];
$('.viewItem').each(function (i, div) {
$.each($(div).data("tags"), function (j, obj) {
if (!(obj.id in hash)) hash[obj.id] = [];
hash[obj.id].push(div);
});
});
// Actual filtering
$('#apply').click(function() {
var filterId = $('#filter').val();
$('.viewItem').hide();
$(hash[filterId]).show();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Filter ID: <input id="filter"><button id="apply">Apply</button><br>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":2,"name":"Tag 02"}]'>1,2</div>
<div class="viewItem" data-tags='[{"id":2,"name":"Tag 02"}]'>2</div>
<div class="viewItem" data-tags='[{"id":1,"name":"Tag 01"},{"id":3,"name":"Tag 03"}]'>1,3</div>
jQuery 过滤器怎么样?
var $viewItems = $('.viewItem');
var filterId = 2;
//Hide all items in object array.
$viewItems.hide();
//Loop thru EACH item and show only those with matching id in array
$viewItems.filter(function (i, el) {
var dataTags = $(el).data("tags");
return dataTags.filter(tag => tag.id === filterId).length
}).show()