Isotope自定义函数无法访问游戏卡片HTML属性的技术求助
问题
开发桌游俱乐部管理网站的游戏展示页面,使用Isotope实现筛选功能,游戏类型、语言筛选正常,但按最小/最大玩家数筛选时,自定义筛选函数无法获取游戏卡片的data-minplayers、data-maxplayers属性值,输出undefined。
技术栈:Laravel 10.8、Bootstrap 5.3、jQuery 3.7.0、Isotope-layout 3.0.6、Masonry-layout 4.2.2
相关代码
JS代码
$(window).on('load', function(){ var filtersFunctions = { minplayers: function(){ var itemValue = $(this).attr('data-minplayers'); var filterValue = $('.isotope-filter-minplayers.active').attr('data-players'); return parseInt(itemValue, 10) >= parseInt(filterValue, 10); }, maxplayers: function(){ var itemValue = $(this).attr('data-maxplayers'); var filterValue = $('.isotope-filter-maxplayers.active').attr('data-players'); return parseInt(itemValue, 10) <= parseInt(filterValue, 10); } }; var filters = {}; var $grid = $('.isotope-grid').isotope({ itemSelector: '.isotope-card', layoutMode: 'masonry' }); $('#isotope-filters').on('click', '.isotope-filter', function(){ var $this = $(this); var $buttonGroup = $this.parents('.isotope-group'); var filterGroup = $buttonGroup.attr('data-filter-group'); if($this.hasClass('active')){ delete filters[filterGroup]; $this.removeClass('active'); } else{ $buttonGroup.find('.isotope-filter').removeClass('active'); $this.addClass('active'); filters[filterGroup] = $this.attr('data-filter'); } var filterValue = filtersFunctions[filters[filterGroup]] || concatValues(filters); $grid.isotope({filter: filterValue}); }); }); function concatValues(obj){ var value = ''; for(var prop in obj){ value += obj[prop]; } return value; }
筛选按钮HTML代码
<div id="isotope-filters"> <div class="card-group shadow"> <div class="card"> <div class="card-body isotope-group" data-filter-group="types"> <h5 class="card-title">Types de jeux</h5> <button type="button" class="btn btn-outline-primary btn-sm isotope-filter" data-filter=".type-null"> Jeux sans types </button> <button type="button" class="btn btn-outline-primary btn-sm isotope-filter" data-filter=".type-1"> Type 1 </button> <button type="button" class="btn btn-outline-primary btn-sm isotope-filter" data-filter=".type-2"> Type 2 </button> <button type="button" class="btn btn-outline-primary btn-sm isotope-filter" data-filter=".type-3"> Type 3 </button> </div> </div> <div class="card"> <div class="card-body isotope-group" data-filter-group="langs"> <h5 class="card-title">Langues</h5> <button type="button" class="btn btn-outline-info btn-sm isotope-filter" data-filter=".lang-fr"> FR </button> <button type="button" class="btn btn-outline-info btn-sm isotope-filter" data-filter=".lang-en"> EN </button> <button type="button" class="btn btn-outline-info btn-sm isotope-filter" data-filter=".lang-pt"> PT </button> </div> </div> <div class="card"> <div class="card-body isotope-group" data-filter-group="minplayers"> <h5 class="card-title">Joueurs min.</h5> <button type="button" class="btn btn-outline-warning btn-sm isotope-filter isotope-filter-minplayers" data-filter="minplayers" data-players="1"> 1 </button> <button type="button" class="btn btn-outline-warning btn-sm isotope-filter isotope-filter-minplayers" data-filter="minplayers" data-players="2"> 2 </button> <button type="button" class="btn btn-outline-warning btn-sm isotope-filter isotope-filter-minplayers" data-filter="minplayers" data-players="3"> 3 </button> </div> </div> <div class="card"> <div class="card-body isotope-group" data-filter-group="maxplayers"> <h5 class="card-title">Joueurs max.</h5> <button type="button" class="btn btn-outline-danger btn-sm isotope-filter isotope-filter-maxplayers" data-filter="maxplayers" data-players="4"> 4 </button> <button type="button" class="btn btn-outline-danger btn-sm isotope-filter isotope-filter-maxplayers" data-filter="maxplayers" data-players="5"> 5 </button> <button type="button" class="btn btn-outline-danger btn-sm isotope-filter isotope-filter-maxplayers" data-filter="maxplayers" data-players="6"> 6 </button> </div> </div> </div> </div>
游戏卡片HTML代码
<div class="row isotope-grid"> <div class="isotope-card lang-fr type-1" data-minplayers="2" data-maxplayers="5"> <div class="card h-100 mb-3 shadow"> <img src="https://picsum.photos/500" class="card-img rounded-bottom-0 object-fit-cover" alt="Adélaïde Allain-Hoarau"> <div class="card-body"> <h5 class="card-title">GAME TITLE</h5> <p class="card-text">GAME DESC</p> <div class="card-text mb-2"> <div class="btn-group btn-group-sm"> <a href="http://lbl.test/games/1" class="btn btn-success">Détails</a> <a href="http://lbl.test/games/1" target="_blank" class="btn btn-success"> <i class="fa-solid fa-arrow-up-right-from-square"></i> </a> </div> </div> </div> <div class="card-footer"> <small class="text-body-secondary">Ajouté le 06/06/2023 à 10:31</small><br> <small class="text-body-secondary">Modifié le 06/06/2023 à 10:31</small> </div> </div> </div> <div class="isotope-card lang-en type-2" data-minplayers="3" data-maxplayers="4"> <div class="card h-100 mb-3 shadow"> <img src="https://picsum.photos/500" class="card-img rounded-bottom-0 object-fit-cover" alt="Adélaïde Allain-Hoarau"> <div class="card-body"> <h5 class="card-title">GAME TITLE</h5> <p class="card-text">GAME DESC</p> <div class="card-text mb-2"> <div class="btn-group btn-group-sm"> <a href="http://lbl.test/games/1" class="btn btn-success">Détails</a> <a href="http://lbl.test/games/1" target="_blank" class="btn btn-success"> <i class="fa-solid fa-arrow-up-right-from-square"></i> </a> </div> </div> </div> <div class="card-footer"> <small class="text-body-secondary">Ajouté le 06/06/2023 à 10:31</small><br> <small class="text-body-secondary">Modifié le 06/06/2023 à 10:31</small> </div> </div> </div> </div>
解决方案
问题根源是自定义筛选函数中this指向异常,且多条件筛选逻辑无法同时兼容类选择器和自定义函数。修改后的代码如下:
$(window).on('load', function(){ var filtersFunctions = { minplayers: function(element){ var $item = $(element); var filterValue = $('.isotope-filter-minplayers.active').attr('data-players'); if(!filterValue) return true; var itemValue = $item.data('minplayers'); return parseInt(itemValue, 10) >= parseInt(filterValue, 10); }, maxplayers: function(element){ var $item = $(element); var filterValue = $('.isotope-filter-maxplayers.active').attr('data-players'); if(!filterValue) return true; var itemValue = $item.data('maxplayers'); return parseInt(itemValue, 10) <= parseInt(filterValue, 10); } }; var filters = {}; var $grid = $('.isotope-grid').isotope({ itemSelector: '.isotope-card', layoutMode: 'masonry' }); $('#isotope-filters').on('click', '.isotope-filter', function(){ var $this = $(this); var $buttonGroup = $this.parents('.isotope-group'); var filterGroup = $buttonGroup.attr('data-filter-group'); if($this.hasClass('active')){ delete filters[filterGroup]; $this.removeClass('active'); } else { $buttonGroup.find('.isotope-filter').removeClass('active'); $this.addClass('active'); filters[filterGroup] = $this.attr('data-filter'); } var filterValue = function(element){ var $element = $(element); var passes = true; for(var group in filters){ var filter = filters[group]; if(filtersFunctions[filter]){ passes = passes && filtersFunctions[filter](element); } else { passes = passes && $element.is(filter); } } return passes; }; $grid.isotope({filter: filterValue}); }); });
修改要点
- 修复元素指向:自定义筛选函数改为接收
element参数,直接操作游戏卡片DOM元素,避免this指向错误。 - 优化属性获取:用jQuery的
data()方法替代attr(),更稳定读取data-*属性。 - 完善多条件筛选:替换原有的
concatValues函数,改为遍历所有筛选组,同时支持类选择器和自定义函数筛选,实现多条件叠加生效。 - 空值兼容处理:当没有激活的玩家数筛选按钮时,默认返回
true,不干扰其他筛选条件。
内容的提问来源于stack exchange,提问作者SatanicGeek
相关产品推荐
相关产品推荐

