优化jQuery/Vanilla JS标签内容筛选:解决动画卡顿与代码冗余
jQuery 优化方案
- 统一事件处理,砍掉冗余代码
不用给每个pill写单独的点击逻辑,直接给所有筛选pill绑定同一个事件,通过$(this).data('tag')拿到当前选中的标签值就行。 - 避免重复动画,解决卡顿问题
筛选时先判断内容项的当前状态,已经显示的就跳过淡入,已经隐藏的就跳过淡出,避免重复触发动画导致的延迟和闪烁。示例代码:// 提前缓存DOM元素,减少重复查询 const $pillFilters = $('.pill-filter'); const $contentItems = $('.content-item'); $pillFilters.on('click', function() { const selectedTag = $(this).data('tag'); // 更新pill激活状态 $pillFilters.removeClass('active'); $(this).addClass('active'); // 遍历内容项做筛选 $contentItems.each(function() { const itemTags = $(this).data('tag').split(' '); // 假设标签用空格分隔,可根据实际调整 const shouldShow = selectedTag === 'all' || itemTags.includes(selectedTag); if (shouldShow) { // 元素隐藏时才执行淡入 if (!$(this).is(':visible')) { $(this).fadeIn(250); } } else { // 元素显示时才执行淡出 if ($(this).is(':visible')) { $(this).fadeOut(250); } } }); }); - 额外性能小调整
- 把动画时长从默认的400ms缩到200-250ms,视觉上更流畅;
- 提前缓存
$contentItems和$pillFilters,避免每次点击都重新查询DOM。
Vanilla JS 轻量优化方案
如果想摆脱jQuery依赖,用原生JS实现更轻量,动画也更可控:
- 事件委托减少绑定
给pill的父容器绑定点击事件,通过事件目标判断是否点击了筛选pill,不用给每个pill单独绑事件。 - 用CSS过渡替代JS动画
把动画逻辑交给CSS处理,比JS驱动的fadeIn/fadeOut更流畅,同时判断元素状态避免重复操作。示例代码:// 缓存DOM元素 const filterContainer = document.querySelector('.pill-container'); const contentItems = document.querySelectorAll('.content-item'); filterContainer.addEventListener('click', (e) => { // 只处理pill的点击事件 if (!e.target.matches('.pill-filter')) return; const selectedTag = e.target.dataset.tag; // 更新pill激活状态 document.querySelectorAll('.pill-filter').forEach(pill => pill.classList.remove('active')); e.target.classList.add('active'); // 筛选内容 contentItems.forEach(item => { const itemTags = item.dataset.tag.split(' '); const shouldShow = selectedTag === 'all' || itemTags.includes(selectedTag); if (shouldShow) { // 元素隐藏时才执行显示动画 if (item.style.display === 'none' || item.style.opacity === '0') { item.style.display = 'block'; // 触发重绘确保过渡生效 void item.offsetWidth; item.style.opacity = '1'; } } else { // 元素显示时才执行隐藏动画 if (item.style.opacity === '1' || item.style.display === 'block') { item.style.opacity = '0'; // 过渡结束后隐藏元素节省布局空间 setTimeout(() => { item.style.display = 'none'; }, 250); } } }); }); - 配合CSS样式
给内容项加基础过渡样式:.content-item { opacity: 1; transition: opacity 0.25s ease; display: block; }
核心思路就是避免对同一元素重复执行状态切换动画,同时缓存DOM元素减少查询开销,从根源解决卡顿和延迟问题。
内容的提问来源于stack exchange,提问作者Joshua Schmitz
相关产品推荐
相关产品推荐

