Razor Pages OnGetAsync捕获弹窗异常 模态框加载相同评论
问题根源
- 「Show comments」按钮的
type属性被设置为了button,该类型按钮不会触发表单提交,因此后端OnGetAsync无法捕获请求,点击时仅触发了Bootstrap模态框弹出,完全没有执行评论加载逻辑。 - 循环渲染帖子卡片时,所有模态框都使用了相同的
id="exampleModal",HTML要求id全局唯一,Bootstrap触发模态框时只会匹配页面中第一个符合id的元素,因此无论点击哪个帖子的按钮,弹出的都是第一个模态框,内容自然完全重复。 - 现有逻辑下模态框内的评论是页面首次加载时就渲染完成的,点击按钮时没有根据当前帖子id重新拉取对应数据。
最小改动解决方案(适配现有后端逻辑)
不需要大幅调整现有代码结构,只需要修改3处:
修复模态框与按钮的绑定关系,保证id全局唯一
在帖子循环块内,给每个模态框和触发按钮拼接帖子Id生成唯一标识:
将Show comments按钮修改为:<button type="submit" name="Id" value="@post.Id" class="btn btn-primary" data-bs-target="#commentsModal_@post.Id">Show comments</button>将对应模态框的标签修改为:
<div class="modal fade" id="commentsModal_@post.Id" tabindex="-1" aria-labelledby="commentsModalLabel_@post.Id" aria-hidden="true">同步修改模态框标题的id绑定:
<h5 class="modal-title" id="commentsModalLabel_@post.Id">@post.Title 评论</h5>增加表单提交后自动弹出模态框的逻辑
表单提交后页面会重新渲染,需要在页面底部(所有模态框渲染完成位置)增加判断,当本次请求携带评论加载参数时,自动触发对应模态框弹出:@if (!string.IsNullOrEmpty(Context.Request.Query["Id"])) { var targetId = Context.Request.Query["Id"]; <script> document.addEventListener('DOMContentLoaded', () => { const modal = new bootstrap.Modal(document.getElementById('commentsModal_@targetId')); modal.show(); }) </script> }
改完后点击Show comments按钮会正常提交GET请求,后端OnGetAsync接收到id参数加载对应评论,页面渲染完成后自动弹出对应帖子的模态框,展示匹配的评论内容。
优化方案(无刷新AJAX版,体验更佳)
如果不想每次点击都整页刷新,可以采用AJAX动态加载方案,页面仅需保留一个全局模态框,不需要重复渲染:
- 将循环内重复的模态框代码全部删除,在页面公共位置放一个全局模态框:
<div class="modal fade" id="globalCommentModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-xl"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">评论列表</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body" id="commentWrap">加载中...</div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button> </div> </div> </div> </div> - 修改Show comments按钮,绑定帖子id参数:
<button type="button" data-postid="@post.Id" class="btn btn-primary comment-btn">Show comments</button> - 增加前端JS逻辑,点击按钮时异步拉取评论填充到模态框后弹出:
document.addEventListener('DOMContentLoaded', () => { const commentModal = new bootstrap.Modal(document.getElementById('globalCommentModal')); const wrap = document.getElementById('commentWrap'); document.querySelectorAll('.comment-btn').forEach(btn => { btn.addEventListener('click', async () => { const postId = btn.dataset.postid; wrap.innerHTML = '加载中...'; commentModal.show(); const res = await fetch(`?handler=PostComments&postId=${postId}`); wrap.innerHTML = await res.text(); }) }) }) - 后端增加对应处理方法,返回指定帖子的评论内容:
其中public async Task<IActionResult> OnGetPostComments(int postId) { var comments = await _dbContext.Comments.Where(c => c.PostId == postId).ToListAsync(); return Partial("_CommentList", comments); }_CommentList是单独写的评论列表分部视图,只负责渲染评论HTML片段即可。
该方案不需要整页刷新,也不会产生重复的模态框DOM,交互体验和页面性能都更好。
内容的提问来源于stack exchange,提问作者Software_Architect
相关产品推荐
相关产品推荐

