解决点赞JS代码仅生效首个图标问题,实现全trend-content生效
循环生成点赞元素的交互修复方案
问题根源
- HTML模板循环生成点赞组件时,错误地给多个元素使用了重复的id属性(
like-icon、like-count),而id在DOM中必须唯一,导致原JS只能获取到第一个元素。 - 尝试修改的JS代码存在变量命名错误(
like-icon不能作为变量名,需用合法标识符),且未关联每个图标对应的计数元素,依然操作全局第一个计数框。
第一步:修正HTML结构
将重复的id替换为class,同时修复button标签重复的class属性:
<section class="trend"> <div class="container"> <div class="flex align-center justify-between trend-header"> <h2 class="subtitle"> <i class="ri-fire-line subtitle-icon"></i> В тренде </h2> <button class="btn btn-outline">Посмотреть все</button> </div> <div class="trend-content"> {% for new in news|slice:"2" %} <div class="trend-card"> <img src="{{new.banner.url}}" alt="newsPhoto" class="trend-background" /> <div class="card-header">{{new.category.title}}</div> <div class="card-bottom"> <h3 class="card-title"> {{new.title}} </h3> <div class="card-btn"> <!-- 把id改为class --> <div class="count like-count">{{new.likes.count}}</div> {% if liked_by %} <!-- 合并重复的class属性 --> <button class="btn-up fa fa-heart"> <a href="javascript:void(0);"><i class="like-icon fa fa-heart" data-news="{{new.id}}"></i></a> </button> {% else %} <button class="btn-up fa fa-heart empty-heart"> <a href="javascript:void(0);"><i class="like-icon fa fa-heart empty-heart" data-news="{{new.id}}"></i></a> </button> {% endif %} </div> </div> </div> {% endfor %} </div> </div> </section>
修改点:
- 将
id="like-icon"改为class="like-icon" - 将
id="like-count"改为class="like-count" - 修复button标签重复的
class属性(合并为一个) - 移除不符合HTML规范的
<li>标签(button内直接放a标签即可)
第二步:修正JS交互逻辑
遍历所有点赞图标,为每个图标绑定点击事件,并关联其对应的计数元素:
// 选中所有.trend-content下的点赞图标 const likeIcons = document.querySelectorAll('.trend-content .like-icon'); likeIcons.forEach(icon => { icon.addEventListener('click', () => { // 获取当前图标的新闻ID const newId = icon.getAttribute('data-news'); const url = `/like_news/${parseInt(newId)}/`; fetch(url, { method: 'GET', headers: { // 修复拼写错误:applicatin → application 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { // 切换当前图标的样式 if(data.liked) { icon.classList.remove('empty-heart'); } else { icon.classList.add('empty-heart'); } // 找到当前图标对应的计数元素 const likeCount = icon.closest('.card-btn').querySelector('.like-count'); // 更新计数(用textContent更安全) likeCount.textContent = data.like_count; }) .catch(error => console.error('点赞请求失败:', error)); }); });
修改点:
- 使用
querySelectorAll选中所有点赞图标,变量名改为复数likeIcons更合理 - 遍历每个图标时用合法变量名
icon(避免连字符) - 通过
closest('.card-btn')定位到当前图标的父容器,再找到对应的计数元素,确保每个图标操作自己的计数框 - 修复请求头的拼写错误
applicatin/json→application/json - 用
textContent替代innerHTML(纯文本更新更安全)
关键说明
- id唯一性:DOM中id必须唯一,循环生成的重复元素必须用class标识
- 元素关联:每个交互元素必须找到自己对应的关联元素(如点赞图标对应自己的计数框),不能全局操作第一个元素
- 变量命名:JS变量名不能使用连字符,需用驼峰式或下划线
内容的提问来源于stack exchange,提问作者abilkaiyrov
相关产品推荐
相关产品推荐

