Express Handlebars中if条件语句无法正确渲染的技术问题
解决Handlebars中
{{#if done}}始终判断为true的问题 我之前开发类似Todo应用时也碰到过完全一样的问题,大概率是Mongoose模型中done字段的类型定义错误导致的,咱们一步步排查解决:
核心原因分析
你提到直接输出{{done}}能正确显示true/false,但{{#if done}}始终走true分支——这说明done的值在数据库里是字符串类型的"true"/"false",而非布尔类型的true/false。Handlebars的{{#if}}判断逻辑会把非空字符串(哪怕是"false")都视为"truthy"值,所以所有Todo都会被加上complete类。
解决方案
1. 修正Mongoose模型的字段类型
首先检查你的../models/todos.js文件,确保done字段被定义为Boolean类型,并且设置默认值为false:
const mongoose = require('mongoose'); const todoSchema = new mongoose.Schema({ todo: { type: String, required: true }, done: { type: Boolean, default: false // 确保新创建的Todo默认未完成 }, googleId: { type: String, required: true } }); module.exports = mongoose.model('Todo', todoSchema);
2. 修复数据库中已有的错误数据
如果之前已经有数据被存成了字符串类型的done值,需要批量更新数据库里的旧数据:
可以在MongoDB终端或数据库管理工具中执行以下命令:
// 将所有"true"字符串改为布尔值true db.todos.updateMany( { done: "true" }, { $set: { done: true } } ); // 将所有"false"字符串改为布尔值false db.todos.updateMany( { done: "false" }, { $set: { done: false } } );
3. 验证数据类型(可选)
为了确认问题已经解决,可以在getTodos控制器里加一行日志,查看done的实际类型:
const todoItems = await Todo.find({ googleId: req.user.googleId }).lean(); // 打印第一个Todo的done值和类型 console.log(todoItems[0]?.done, typeof todoItems[0]?.done);
正常情况下应该输出false boolean或true boolean,而不是"false" string。
备选方案:使用严格相等判断(临时方案)
如果暂时无法修改数据库,也可以在Handlebars中使用严格相等判断绕过问题——不过这只是临时方案,根源还是要修复数据类型:
首先确保你的Express Handlebars注册了eq助手(默认通常已注册,若没有需手动添加),然后修改模板:
{{#each todo}} <li data-id="{{_id}}"> {{done}} {{#eq done true}} <span class="complete">{{todo}}</span> {{else}} <span class="incomplete">{{todo}}</span> {{/eq}} <span class="fa fa-trash delete-todo"></span> </li> {{/each}}
内容的提问来源于stack exchange,提问作者Julian
相关产品推荐
相关产品推荐

