修改jQuery实现HTML表格仅点击星标触发收藏功能
问题根因
原代码逻辑存在两处设计缺陷,导致无法满足需求:
- 收藏切换的点击事件直接绑定在整行
tr元素上,点击行内任意区域都会触发逻辑 - 页面加载还原收藏状态时,是通过模拟触发
tr的点击事件实现的,一旦把事件绑定对象改成星标元素,这部分还原逻辑会直接失效
修改后完整代码
const showFavs = function(key, favs) { if (!favs) return; key = key.replace("favs", ""); favs = JSON.parse(favs); $.each(favs, function(i, fav) { const selector = "#" + key + " tr td[data-id='" + fav + "']"; const $row = $(selector).closest("tr"); // 直接切换星标状态,不再依赖触发tr点击 $row.find('img.white-star').hide(); $row.find('img.yellow-star').show(); }); }; $(function() { // 事件委托绑定星标点击事件,动态生成的表格行也能正常响应 $('tbody').on('click', 'img.white-star, img.yellow-star', function(e) { // 阻止事件冒泡,避免触发行上其他绑定事件 e.stopPropagation(); const $row = $(this).closest("tr"); const $parentTable = $row.closest("tbody"); // 切换当前行的星标显隐状态 $row.find('img.white-star').toggle(); $row.find('img.yellow-star').toggle(); // 收集所有已收藏项存入本地存储 const $favs = $("tr", $parentTable).has('img.yellow-star:visible'); const favs = $favs.find("td:first").map((i, fav) => $(fav).data("id")).get(); localStorage.setItem($parentTable.attr("id") + "favs", JSON.stringify(favs)); }) // 页面加载时还原本地存储的收藏状态 Object.keys(localStorage).forEach(key => { if (key.endsWith("favs")) showFavs(key, localStorage.getItem(key)); }); // 仅显示已收藏项的筛选逻辑 const $onlyRated = $("#onlyrated"); if ($onlyRated.length>0) { $onlyRated.on("click",function() { if (this.checked) { $("tr").find('img.white-star:visible').each(function() { $(this).closest("tr").hide(); }); } else { $("tr").find('img.white-star').each(function() { $(this).closest("tr").show(); }); } }); } });
适配说明
- 如果你的星标元素是包裹在特定容器(比如class为
star-wrap的div)内,只需要把事件绑定的目标选择器从img.white-star, img.yellow-star改成对应容器的选择器即可 - 所有原有功能(本地持久化存储、收藏筛选)完全保留,没有功能损失
- 新增的事件冒泡阻止逻辑不会影响表格行上绑定的其他点击事件(比如行跳转、行选中之类的功能)
内容的提问来源于stack exchange,提问作者MathiasWainer
相关产品推荐
相关产品推荐

