接上篇黑马旅游网(番外2):用户收藏分页展示,在本篇博客中,我将实现另一个与收藏相关的功能:取消收藏。
原始的旅游详情页面只有一个 点击收藏 的按钮。在我的实现方式中:在 点击收藏 旁边添加了一个 取消收藏 的按钮,两个按钮的样式相反。当用户没有登录或登录后没有收藏此线路,则 点击收藏 为红色且可点击,取消收藏 为灰色且不可点击;反之亦然。
实现取消收藏,前端的重点在于对两个按钮状态的切换。在黑马旅游网(8):旅游线路收藏中,添加收藏 按钮的状态切换是采用 AJAX 方式实现,这种方式避免跳转页面,我在进一步开发时也是基于之前的代码:为 取消收藏 绑定单击事件,采用对仗的方式补充了取消收藏的代码。但是功能开发完毕后,这种异步请求只能满足一次请求有效,再次请求就必须刷新页面。例如:当点击 添加收藏 时,利用 AJAX 将两个按钮的状态做一次切换,但是再次点击请求失效。在此处,我的解决方式是每次单击事件结束前都刷新一次页面,保证添加和取消动作的连贯性。其它读者要是有更好的实现方式的话,欢迎私信/评论分享和讨论。
相比前端,后端的执行逻辑比较清晰和简单了。在 Servlet 层获取 uid 和 rid,然后依次传入 Service 层和 Dao 层执行具体的数据库删除业务即可。前台通过重新查询的方式更新页面,调用之前定义的相关代码即可。
RouteServlet.java
/** * 取消收藏 */ public void removeFavorite(HttpServletRequest request, HttpServletResponse response) { // 1.获取线路id String rid = request.getParameter("rid"); // 2.获取用户id User user = (User) request.getSession().getAttribute("user"); if (user == null) return; // 未登录无法收藏,直接跳出方法 int uid = user.getUid(); // 3.调用service执行添加收藏 favoriteService.remove(rid, uid); }FavoriteServiceImpl.java
/** * 取消收藏路线 * @param rid 旅游路线id * @param uid 用户id */ @Override public void remove(String rid, int uid) { favoriteDao.remove(Integer.parseInt(rid), uid); }FavoriteDaoImpl.java
/** * 删除收藏路线 * @param rid 旅游路线id * @param uid 用户id */ @Override public void remove(int rid, int uid) { String sql = "DELETE FROM tab_favorite WHERE rid = ? AND uid = ?"; template.update(sql, rid, uid); }前端的改动比较大,主要体现在页面加载以及两个按钮的单击事件处理上。
route_detail.html
页面加载/** * 发送请求,判断用户是否收藏过该线路 */ $(function fun () { let rid = getParameter("rid"); $.get("route/isFavorite", {rid: rid}, function (flag) { if (flag) { // 用户已收藏 // 设置收藏按钮样式 <a class="btn already" disabled="disabled"> let favor_selector = $("#favorite"); favor_selector.addClass("already"); favor_selector.attr("disabled", "disabled"); favor_selector.removeAttr("onclick"); // 删除按钮点击事件 let cancel_favor_selector = $("#cancel_favorite"); cancel_favor_selector.removeClass("already"); cancel_favor_selector.removeAttr("disabled"); cancel_favor_selector.attr("onclick"); } else { // 用户未收藏 // 设置收藏按钮样式 <a class="btn already" disabled="disabled"> let favor_selector = $("#favorite"); favor_selector.removeClass("already"); favor_selector.removeAttr("disabled", "disabled"); favor_selector.attr("onclick"); // 删除按钮点击事件 let cancel_favor_selector = $("#cancel_favorite"); cancel_favor_selector.addClass("already"); cancel_favor_selector.attr("disabled"); cancel_favor_selector.removeAttr("onclick"); } }); }); 点击收藏/** * 点击收藏按钮触发方法 */ function addFavorite() { let rid = getParameter("rid"); // 1.判断用户是否登陆 $.get("user/findOne", {}, function (user) { if (user) { // 用户登陆 $.get("route/addFavorite", {rid: rid}, function () { }); // 按钮渲染更新方式1:刷新页面 // location.reload(); // 按钮渲染更新方式2:发送一个异步请求 $.get("route/isFavorite", {rid: rid}, function (flag) { if (flag) { // 用户已收藏 // 设置收藏按钮样式 <a class="btn already" disabled="disabled"> let favor_selector = $("#favorite"); favor_selector.addClass("already"); favor_selector.attr("disabled", "disabled"); favor_selector.removeAttr("onclick"); // 删除按钮点击事件 let cancel_favor_selector = $("#cancel_favorite"); cancel_favor_selector.removeClass("already"); cancel_favor_selector.removeAttr("disabled"); cancel_favor_selector.attr("onclick"); } else { // 用户未收藏 // 设置收藏按钮样式 <a class="btn already" disabled="disabled"> let favor_selector = $("#favorite"); favor_selector.removeClass("already"); favor_selector.removeAttr("disabled", "disabled"); favor_selector.attr("onclick"); // 删除按钮点击事件 let cancel_favor_selector = $("#cancel_favorite"); cancel_favor_selector.addClass("already"); cancel_favor_selector.attr("disabled"); cancel_favor_selector.removeAttr("onclick"); } }); $.get("route/findOne", {rid: rid}, function (route) { $("#favoriteCount").html("已收藏" + route.count + "次"); // 设置收藏次数 }); location.reload(); // AJAX只能保证一次请求是有效的,不刷一下的话无法保证动作的连贯性 } else { // 用户未登录 alert("您尚未登陆,请登录"); location.href = "http://localhost/travel/login.html"; } }) } 取消收藏/** * 取消收藏按钮触发方法 */ function removeFavorite () { let rid = getParameter("rid"); // 1.判断用户是否登陆 $.get("user/findOne", {}, function (user) { if (user) { // 用户登陆 $.get("route/removeFavorite", {rid: rid}, function () { }); // 按钮渲染更新方式1:刷新页面 // location.reload(); // 按钮渲染更新方式2:发送一个异步请求 $.get("route/isFavorite", {rid: rid}, function (flag) { if (flag) { // 用户已收藏 // 设置收藏按钮样式 <a class="btn already" disabled="disabled"> let favor_selector = $("#favorite"); favor_selector.addClass("already"); favor_selector.attr("disabled", "disabled"); favor_selector.removeAttr("onclick"); // 删除按钮点击事件 let cancel_favor_selector = $("#cancel_favorite"); cancel_favor_selector.removeClass("already"); cancel_favor_selector.removeAttr("disabled"); cancel_favor_selector.attr("onclick"); } else { // 用户未收藏 // 设置收藏按钮样式 <a class="btn already" disabled="disabled"> let favor_selector = $("#favorite"); favor_selector.removeClass("already"); favor_selector.removeAttr("disabled", "disabled"); favor_selector.attr("onclick"); // 删除按钮点击事件 let cancel_favor_selector = $("#cancel_favorite"); cancel_favor_selector.addClass("already"); cancel_favor_selector.attr("disabled"); cancel_favor_selector.removeAttr("onclick"); } }); $.get("route/findOne", {rid: rid}, function (route) { $("#favoriteCount").html("已收藏" + route.count + "次"); // 设置收藏次数 }); location.reload(); // AJAX只能保证一次请求是有效的,不刷一下的话无法保证动作的连贯性 } else { // 用户未登录 alert("您尚未登陆,请登录"); location.href = "http://localhost/travel/login.html"; } }); };项目课程链接:https://www.bilibili.com/video/BV1CE411E7h4 完整课程连接:https://www.bilibili.com/video/BV1uJ411k7wy 《黑马旅游网》系列博客及笔者源码传送门:https://blog.csdn.net/xing123456jl/article/details/109173068