如何使用Node.js与Handlebars实现博客申请按钮截止后自动禁用
原代码问题排查
你目前的代码核心问题是混淆了前后端代码的执行边界:
- Node.js 后端路由中写的
document.getElementById属于浏览器端API,在服务端完全无法执行,你定义的showButton函数既没有调用也没有传递给模板,模板中判断用的showButton变量根本不存在 - GET请求的
req.body是空的,你无法从这里拿到每个帖子的dateToApply字段,判断逻辑需要针对每一个单独的帖子处理,而不是全局判断一次
正确实现步骤
1. 改造后端路由逻辑
删掉路由中你写的dateNow、applyDate、button、showButton相关无效代码,在查询到帖子列表后,给每个帖子新增标记申请状态的字段再传给模板:
router.get('/', (req, res)=>{ const perPage = 10; const page = req.query.page || 1; Post.find({}) .sort({date: 'desc'}) .skip((perPage*page)-perPage) .limit(perPage) .then(posts => { const currentTime = Date.now() // 遍历处理每个帖子的申请状态 const processedPosts = posts.map(post => { const postPlain = post.toObject() // 规则:没设置截止日期默认可申请,设置了的话当前时间小于截止时间可申请 postPlain.canApply = postPlain.dateToApply ? currentTime < postPlain.dateToApply.getTime() : true return postPlain }) Post.count().then(postCount=>{ Category.find({}).then(categories => { res.render('home/index', { posts: processedPosts, categories: categories, current: parseInt(page), pages: Math.ceil(postCount/perPage) }); }); }); }); });
2. 修改Handlebars模板
首先注意循环渲染的元素不要用重复id,把按钮id改成class,再根据canApply字段控制按钮状态:
- 如果需求是截止后隐藏按钮,修改对应部分为:
{{#if canApply}} <button class="btn btn-info apply-btn">Apply</button> {{/if}}
- 如果需求是截止后禁用按钮(保留显示),修改对应部分为:
<button class="btn btn-info apply-btn" {{#unless canApply}}disabled{{/unless}}>Apply</button>
可选:前端兜底校验(避免服务端和客户端时间差问题)
如果需要更严谨的校验,可以在前端加一层实时判断,模板中给按钮加截止时间的自定义属性:
<button class="btn btn-info apply-btn" data-deadline="{{dateToApply}}" {{#unless canApply}}disabled{{/unless}}>Apply</button>
然后在页面底部加前端JS:
<script> const now = Date.now() document.querySelectorAll('.apply-btn').forEach(btn => { const deadline = new Date(btn.dataset.deadline).getTime() if(!isNaN(deadline) && now > deadline) btn.disabled = true }) </script>
内容的提问来源于stack exchange,提问作者exitcode_1
相关产品推荐
相关产品推荐

