在 jQuery 中过滤不同类型过滤器组合的最快策略(就性能而言)是什么?
在这个例子中,我使用“Radios + Select + Checkbox”并需要它们同时操作。
JS Bin 链接:https : //jsbin.com/wegopom/3/edit? js, output
我<img>在基于以下内容的传单地图中定位标记:
过滤器的速度是核心,因为这张地图将显示成百上千的标记图像。
对于收音机,(“变体”类)...我有一个更改功能:
jQuery(document).on("change", ".variation", function() {
Run Code Online (Sandbox Code Playgroud)
对于选择,(“filterbottler”ID)...我有第二个更改功能:
jQuery('#filterbottler').change(function(){
Run Code Online (Sandbox Code Playgroud)
对于复选框,(“中断”ID)...我有第三个更改功能:
jQuery('#outages').change(function(){
Run Code Online (Sandbox Code Playgroud)
使用一堆 IF 语句和相邻/链接的类(如 img.variation.bottler 会非常慢)使其中两个更改函数协同工作很简单……但是现在我添加了第三个过滤器,这似乎是过载,现在我很难将大脑围绕在每个过滤场景中。
JS Bin @ https://jsbin.com/wego/3/edit?js, 输出功能这三个过滤器中的每一个都独立工作......
目标是让前三个过滤器(Variation、Bottler 和 Outages)以最快和最有效的方式同时协同工作。我该如何解决这个问题?
jQuery(document).ready(function($){
// Filter 1) by Variation
jQuery(document).on("change", ".variation", function() {
var bottlerValue = jQuery("#filterbottler").find("option:selected").val();
var bottlerClass = '.field-ccb-cached__'+bottlerValue;
// marker groups to be used in exclusionary :not() statements so they aren't affected by the filters... e.g. marker-icon.png & marker-icon-2x.png are "My Location" markers
var mainMarkers = '[src$="bottler_22px.png"],[src$="marker-icon.png"],[src$="marker-icon-2x.png"]';
var includeOutageMarkers = '[src$="bottler_22px.png"],[src$="marker-icon.png"],[src$="marker-icon-2x.png"],[src$="cross_22px.png"]';
if (this.id == "map-filters-show-all") {
jQuery('.leaflet-marker-pane img:not('+mainMarkers+')').show(500);
}
else if (this.id == "map-filters-16oz-cans") {
jQuery('.leaflet-marker-pane img:not('+includeOutageMarkers+',.field-report-variation__16oz-cans)').hide(500);
jQuery('.leaflet-marker-pane img.field-report-variation__16oz-cans').show(500);
} else if (this.id == "map-filters-12oz-cans") {
jQuery('.leaflet-marker-pane img:not('+includeOutageMarkers+',.field-report-variation__12oz-cans)').hide(500);
jQuery('.leaflet-marker-pane img.field-report-variation__12oz-cans').show(500);
} else if (this.id == "map-filters-fountain-surge") {
jQuery('.leaflet-marker-pane img:not('+includeOutageMarkers+',.field-report-variation__fountain-surge)').hide(500);
jQuery('.leaflet-marker-pane img.field-report-variation__fountain-surge').show(500);
} else if (this.id == "map-filters-fountain-surge-red-berry-blast") {
jQuery('.leaflet-marker-pane img:not('+includeOutageMarkers+',.field-report-variation__fountain-surge-red-berry-blast)').hide(500);
jQuery('.leaflet-marker-pane img.field-report-variation__fountain-surge-red-berry-blast').show(500);
}
});
// Filter 2) by Bottling Company (select box)
jQuery('#filterbottler').change(function(){
var bottlerValue = jQuery("#filterbottler").find("option:selected").val();
var bottlerClass = '.field-ccb-cached__'+bottlerValue;
if (bottlerClass != '.field-ccb-cached___none') {
jQuery('.leaflet-marker-pane img:not([src$="bottler_22px.png"],[src$="marker-icon.png"],[src$="marker-icon-2x.png"],[src$="cross_22px.png"],'+bottlerClass+')').hide(500);
jQuery('.leaflet-marker-pane img'+bottlerClass).show(500);
}
if (bottlerClass === '.field-ccb-cached___none') {
jQuery('.leaflet-marker-pane img:not([src$="bottler_22px.png"],[src$="marker-icon.png"],[src$="marker-icon-2x.png"])').show(500);
}
});
// Filter 3) Show Outage Reports (checkbox on/off)
jQuery('#outages').change(function(){
if(this.checked){
jQuery('.leaflet-marker-pane img[src$="cross_22px.png"],[src$="exclamation_22px.png"]').fadeToggle(500);
jQuery.cookie('outagemarkers', true);
}
else {
jQuery('.leaflet-marker-pane img[src$="cross_22px.png"],[src$="exclamation_22px.png"]').fadeToggle(500);
jQuery.cookie('outagemarkers', false);
}
});
Run Code Online (Sandbox Code Playgroud)
'*'当过滤器不活动时(设置为show-all或none)用作后备 vaklue。在纯JS中,我使用布尔值false来“关闭”过滤器,然后在filter()稍后使用时,如果过滤器设置为false,我手动将过滤条件设置为true来绕过它。find()或filter()来查找仅获取该选项值的选项selected,而是简单地获取元素本身的值<select>。在 jQuery 中:bottlerSelect.val(),在纯 JS 中:bottlerSelect.value.为了最大限度地提高程序的性能,最好将所有过滤器放在一个块中,然后对所有过滤器进行过滤。一旦我们定义了所有所需的过滤器,我们就可以通过过滤器选择器过滤所有标记并将它们保存到变量中matchedMarkers。然后,我们可以将那些不匹配的内容保存到单独的unmatchedMarkers一行中:unmatchedMarkers = allMarkers.not(matchedMarkers);
总而言之,它实际上是一个非常简单且轻量级的程序,并且在普通 JS 中它可能会更加高效,我希望在接下来的一两天内再次访问它。
CodePen链接:https://cdpn.io/e/943560466fc36d61871d01b57739137d
jQuery(document).ready(function($){
var allMarkers = $('.leaflet-marker-icon'),
variationPrefix = 'field-report-variation__',
bottlerPrefix = 'field-ccb-cached__',
outagesSelector = ':not([src$="cross_22px.png"],[src$="exclamation_22px.png"])',
variationInputs = $('input.variation'),
bottlerSelect = $('#filterbottler'),
outagesCheckbox = $('#outages');
$(document).on('change', '.variation, #filterbottler, #outages', function() {
var variationSelector = '.'+variationPrefix+variationInputs.filter(':checked').attr('id').split('-').slice(2).join('-').toLowerCase().replace(/ /g,'-'),
variationFilter = variationSelector.endsWith('__show-all') ? '*' : variationSelector + ',:not([class*="'+variationPrefix+'"])',
bottlerSelector = '.'+bottlerPrefix+bottlerSelect.val(),
bottlerFilter = bottlerSelector.endsWith('___none') ? '*' : bottlerSelector + ',:not([class*="'+bottlerPrefix+'"])',
outagesFilter = outagesCheckbox.is(':checked') ? '*' : outagesSelector,
matchedMarkers = allMarkers.filter(variationFilter).filter(bottlerFilter).filter(outagesFilter),
unmatchedMarkers = allMarkers.not(matchedMarkers);
matchedMarkers.fadeIn(500);
unmatchedMarkers.fadeOut(500);
});
});Run Code Online (Sandbox Code Playgroud)
.leaflet-marker-pane{width:100%;border:1px solid #000}table td{min-width:25px;height:30px;border:1px solid gray;padding:10px}Run Code Online (Sandbox Code Playgroud)
<div class="form-item" id="map-filter-content"> <label style="font-size:18px;">Filter Reports by Variation <i>(must either "Show All" or be a specific variation):</i></label><div class="form-checkboxes"> <input type="radio" value="Show All" name="variation" class="variation" id="map-filters-show-all" checked=""> <label>Show All</label><br> <input type="radio" value="16oz Cans" name="variation" class="variation" id="map-filters-16oz-cans"> <label>16oz Cans</label><br> <input type="radio" value="12oz Cans" name="variation" class="variation" id="map-filters-12oz-cans"> <label>12oz Cans</label><br> <input type="radio" value="Fountain SURGE" name="variation" class="variation" id="map-filters-fountain-surge"> <label>Fountain SURGE</label><br> <input type="radio" value="Fountain SURGE Red Berry Blast" name="variation" class="variation" id="map-filters-fountain-surge-red-berry-blast"> <label>Fountain SURGE Red Berry Blast</label></div><hr style="margin:15px 0 10px 0;"><div class="field-widget-options-select form-wrapper"><div class="control-group form-type-select form-item"> <label style="font-size:18px;">Filter by Bottling Company <i>(must either "Show All" or be a specific bottler):</i></label><div class="controls"> <select id="filterbottler" class="form-select"><option value="_none">- Select All Coca-Cola Bottlers -</option><option value="190">ABARTA</option><option value="191">Aberdeen Coca-Cola</option><option value="192">Ada Coca-Cola</option><option value="193">Atlantic Coca-Cola</option><option value="194">Bemidji Coca-Cola</option><option value="195">Binks Coca-Cola</option><option value="196">Canyon City Coca-Cola</option><option value="197">Cedar City Coca-Cola</option><option value="198">Chesterman Coca-Cola</option><option value="199">Clark</option><option value="200">Coca-Cola Consolidated</option><option value="186">Coca-Cola High Country</option><option value="187">Coca-Cola Southwest</option><option value="177">Coca-Cola UNITED</option><option value="201">Columbus Coca-Cola</option><option value="202">Corinth</option><option value="203">Decatur</option><option value="204">Deming Coca-Cola</option><option value="205">Dickinson Coca-Cola</option><option value="206">Durango Coca-Cola</option><option value="207">Durham Coca-Cola</option><option value="183">Emporia Coca-Cola</option><option value="208">Florida Coca-Cola</option><option value="209">Fort Smith Coca-Cola</option><option value="244">Glasgow Coca-Cola</option><option value="210">Glendive Coca-Cola</option><option value="211">Great Lakes Coca-Cola</option><option value="212">Hancock</option><option value="213">Heartland Coca-Cola</option><option value="214">Hot Springs Coca-Cola</option><option value="215">Huntsville</option><option value="216">Idabel Coca-Cola</option><option value="217">Internation Falls</option><option value="218">Jefferson Coca-Cola</option><option value="219">Ketchikan</option><option value="220">Kokomo Coca-Cola</option><option value="178">Lehrkinds</option><option value="184">Liberty Coca-Cola</option><option value="221">Love Coca-Cola</option><option value="222">Lufkin Coca-Cola</option><option value="223">Macon</option><option value="224">Magnolia Coca-Cola</option><option value="225">Maui</option><option value="226">Meridian</option><option value="227">MiddlesBoro</option><option value="179">Mile High</option><option value="228">Minden Coca-Cola</option><option value="182">Nashville Coca-Cola</option><option value="229">Northern New England</option><option value="230">ODOM</option><option value="231">Orangeburg Coca-Cola</option><option value="232">Ozarks Coca-Cola</option><option value="233">Pulaski Coca-Cola</option><option value="176">Reyes Coca-Cola</option><option value="234">Rock Hill Coca-Cola</option><option value="235">Santa Fe Coca-Cola</option><option value="236">Sitka</option><option value="237">Sooner Coca-Cola</option><option value="185">Swire Coca-Cola</option><option value="181">Timber Country</option><option value="238">Trenton Coca-Cola</option><option value="180">Tullahoma Coca-Cola</option><option value="239">Union City</option><option value="174">Viking Coca-Cola</option><option value="240">Washington Coca-Cola</option><option value="241">Williston Coca-Cola</option><option value="188">Winfield Coca-Cola</option><option value="242">Winona Coca-Cola</option><option value="243">Yakima Coca-Cola</option> </select></div></div></div><hr style="margin:15px 0 10px 0;"><div class="mwcheck"> <input type="checkbox" id="outages" checked> <label>Show Outage Reports <i>(must turn these icons on/off with other filters intact: <img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/exclamation_22px.png"> & <img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/cross_22px.png">)</i></label></div></div><hr><div class="leaflet-marker-pane"><table><tr><td><img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/check_22px.png" class="leaflet-marker-icon tag-inside-marker field-report-variation__16oz-cans field-ccb-cached__190"></td><td> < Has Class "field-report-variation__16oz-cans" <b>(16oz Cans)</b><br> < Has Class "field-ccb-cached__190" <b>("ABARTA" Bottling Company)</b></td></tr><tr><td><img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/check_22px.png" class="leaflet-marker-icon tag-inside-marker field-report-variation__12oz-cans field-ccb-cached__190"></td><td> < Has Class "field-report-variation__12oz-cans" <b>(12oz Cans)</b><br> < Has Class "field-ccb-cached__190" <b>("ABARTA" Bottling Company)</b></td></tr><tr><td><img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/check_22px.png" class="leaflet-marker-icon tag-inside-marker field-report-variation__12oz-cans field-ccb-cached__191"></td><td> < Has Class "field-report-variation__12oz-cans" <b>(12oz Cans)</b><br> < Has Class "field-ccb-cached__191" <b>("Aberdeen Coca-Cola" Bottling Company)</b></td></tr><tr><td><img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/exclamation_22px.png" class="leaflet-marker-icon tag-inside-marker field-report-variation__16oz-cans field-ccb-cached__190"></td><td> < Has Class "field-report-variation__16oz-cans" <b>(16oz Cans)</b><br> < Has Class "field-ccb-cached__190" <b>("ABARTA Coca-Cola" Bottling Company)</b></td></tr><tr><td><img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/exclamation_22px.png" class="leaflet-marker-icon tag-inside-marker field-report-variation__16oz-cans field-ccb-cached__191"></td><td> < Has Class "field-report-variation__16oz-cans" <b>(16oz Cans)</b><br> < Has Class "field-ccb-cached__191" <b>("Aberdeen Coca-Cola" Bottling Company)</b></td></tr><tr><td><img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/exclamation_22px.png" class="leaflet-marker-icon tag-inside-marker field-report-variation__12oz-cans field-ccb-cached__191"></td><td> < Has Class "field-report-variation__12oz-cans" <b>(12oz Cans)</b><br> < Has Class "field-ccb-cached__191" <b>("Aberdeen Coca-Cola" Bottling Company)</b></td></tr><tr><td><img src="https://surgemovement.org/sites/all/themes/surgemovement/images/ip_geoloc_custom_markers/cross_22px.png" class="leaflet-marker-icon tag-inside-marker field-ccb-cached__191"></td><td> < Has Class "field-ccb-cached__191" <b>("Aberdeen Coca-Cola" Bottling Company)</b> <br><br>This always shows unless:<br>1) "Show Outage Reports" is deselected... or <br>2) Another bottling company (e.g. ABARTA is selected)<br></td></tr></table></div>
<script src="https://code.jquery.com/jquery-1.8.3.js"></script>Run Code Online (Sandbox Code Playgroud)
CodePen链接:https://cdpn.io/e/d9e89a278a7bb190841c19f53c376033
这个纯原生 JavaScript 解决方案甚至比 jQuery 解决方案更简单,如果您可以从该项目中完全排除 jQuery 并坚持使用纯 JS,它将大大提高性能。无需等待页面完全加载。只需在 HTML 内容之后立即运行 JavaScript,一切就会按预期工作。这也使得我们的过滤方法具有更大的灵活性。我们可以在一个过滤器方法中运行所有条件,并立即淡入或淡出关联的标记元素,而不是连续运行三个过滤器函数。另外,为了提高性能,我没有依赖 JavaScript 来设置淡入淡出过渡的动画,而是在 CSS 中创建了两个简单的状态:默认状态 ( opacity: 1) 和由 类 表示的过滤状态.filtered。所有的淡入和淡出都在 CSS 中完成,通过简单的 CSS 过渡来确定是否.filtered应用该类。
这是纯 JavaScript 代码:
const allMarkers = Array.from(document.querySelectorAll('.leaflet-marker-icon')),
variationPrefix = 'field-report-variation__',
bottlerPrefix = 'field-ccb-cached__',
outagesSelector = ':not([src$="cross_22px.png"],[src$="exclamation_22px.png"])',
variationInputs = Array.from(document.querySelectorAll('input.variation')),
bottlerSelect = document.getElementById('filterbottler'),
outagesCheckbox = document.getElementById('outages');
document.addEventListener('change', e => {
if (e.target?.matches('.variation, #filterbottler, #outages')) {
const variationSelector = '.'+variationPrefix+variationInputs.filter(input => input.checked)[0].id.split('-').slice(2).join('-').toLowerCase().replace(/ /g,'-'),
variationFilter = variationSelector.endsWith('__show-all') ? false : variationSelector + ',:not([class*="'+variationPrefix+'"])',
bottlerSelector = '.'+bottlerPrefix+bottlerSelect.value,
bottlerFilter = bottlerSelector.endsWith('___none') ? false : bottlerSelector + ',:not([class*="'+bottlerPrefix+'"])',
outagesFilter = outagesCheckbox.checked ? false : outagesSelector;
allMarkers.forEach(marker => ((variationFilter ? marker.matches(variationFilter) : true) && (bottlerFilter ? marker.matches(bottlerFilter) : true) && (outagesFilter ? marker.matches(outagesFilter) : true)) ? marker.classList.remove('filtered') : marker.classList.add('filtered'));
}
});Run Code Online (Sandbox Code Playgroud)
.leaflet-marker-pane{width:100%;border:1px solid #000}table td{min-width:25px;height:30px;border:1px solid gray;padding:10px}
.leaflet-marker-icon {
opacity: 1;
transition: opacity 500ms ease-out;
}
.leaflet-marker-icon.filtered {
opacity: 0;
}Run Code Online (Sandbox Code Playgroud)
<div class="form-item" id="map-filter-content"> <label style="font-size:18px;">Filter Reports by Variation <i>(must either "Show All" or be a specific variation):</i></label><div class="form-checkboxes"> <input type="radio" value="Show All" name="variation" class="variation" id="map-filters-show-all" checked=""> <label>Show All</label><br> <input type="radio" value="16oz Cans" name="variation" class="variation" id="map-filters-16oz-cans"> <label>16oz Cans</label><br> <input type="radio" value="12oz Cans" name="variation" class="variation" id="map-filters-12oz-cans"> <label>12oz Cans</label><br> <input type="radio" value="Fountain SURGE" name="variation" class="variation" id="map-filters-fountain-surge"> <label>Fountain SURGE</label><br> <input type="radio" value="Fountain SURGE Red Berry Blast" name="variation" class="variation" id="map-filters-fountain-surge-red-berry-blast"> <label>Fountain SURGE Red Berry Blast</label></div><hr style="margin:15px 0 10px 0;"><div class="field-widget-options-select form-wrapper"><div class="control-group form-type-select form-item"> <label style="font-size:18px;">Filter by Bottling Company <i>(must either "Show All" or be a specific bottler):</i></label><div class="controls"> <select id="filterbottler" class="form-select"><option value="_none">- Select All Coca-Cola Bottlers -</option><option value="190">ABARTA</option><option value="191">Aberdeen Coca-Cola</option><option value="192">Ada Coca-Cola</option><option value="193">Atlantic Coca-Cola</option><option value="194">Bemidji Coca-Cola</option><option value="195">Binks Coca-Cola</option><option value="196">Canyon City Coca-Cola</option><option value="197">Cedar City Coca-Cola</option><option value="198">Chesterman Coca-Cola</option><option value="199">Clark</option><option value="200">Coca-Cola Consolidated</option><option value="186">Coca-Cola High Country</option><option value="187">Coca-Cola Southwest</option><option value="177">Coca-Cola UNITED</option><option value="201">Columbus Coca-Cola</option><option value="202">Corinth</option><option value="203">Decatur</option><option value="204">Deming Coca-Cola</option><option value="205">Dickinson Coca-Cola</option><option value="206">Durango Coca-Cola</option><option value="207">Durham Coca-Cola</option><option value="183">Emporia Coca-Cola</option><option value="208">Florida Coca-Cola</option><option value="209">Fort Smith Coca-Cola</option><option value="244">Glasgow Coca-Cola</option><option value="210">Glendive Coca-Cola</option><option value="211">Great Lakes Coca-Cola</option><option value="212">Hancock</option><option value="213">Heartland Coca-Cola</option><option value="214">Hot Springs Coca-Cola</option><option value="215">Huntsville</option><option value="216">Idabel Coca-Cola</option><option value="217">Internation Falls</option><option value="218">Jefferson Coca-Cola</option><option value="219">Ketchikan</option><option value="220">Kokomo Coca-Cola</option><option value="178">Lehrkinds</option><option value="184">Liberty Coca-Cola</option><option value="221">Love Coca-Cola</option><option value="222">Lufkin Coca-Cola</option><option value="223">Macon</option><option value="224">Magnolia Coca-Cola</option><option value="225">Maui</option><option value="226">Meridian</option><option value="227">MiddlesBoro</option><option value="179">Mile High</option><option value="228">Minden Coca-Cola</option><option value="182">Nashville Coca-Cola</option><option value="229">Northern New England</option><option value="230">ODOM</option><option value="231">Orangeburg Coca-Cola</option><option value="232">Ozarks Coca-Cola</option><option value="233">Pulaski Coca-Cola</option><option value="176">Reyes Coca-Cola</option><option value="234">Rock Hill Coca-Cola</option><option value="235">Santa Fe Coca-Cola</option><option value="236">Sitka</option><option value="237">Sooner Coca-Cola</option><option value="185">Swire Coca-Cola</option><option value="181">Timber C