在Handlebars中根据数据条件动态应用CSS样式
Handlebars是一款轻量级的JavaScript模板引擎,它通过简单的语法帮助开发者将数据与HTML模板结合,快速生成动态页面内容。在实际开发中,我们经常需要根据不同的数据状态为页面元素应用不同的CSS样式,比如根据订单状态显示不同颜色的标签、根据数值大小调整进度条样式等,Handlebars提供的条件判断语法可以很好地支持这类需求。
Handlebars条件判断基础
Handlebars内置了<if>和<unless>两个块级助手(Block Helper),用于实现基本的条件判断逻辑:
<if>:当判断条件为真时,渲染块内的内容<unless>:当判断条件为假时,渲染块内的内容,相当于<if>的反向判断
同时Handlebars还支持通过自定义助手扩展条件判断能力,实现更复杂的多条件、逻辑运算等场景。
基础场景:单条件动态样式
最常见的需求是根据单个数据字段的值,为元素添加不同的样式类。比如我们有一个用户列表数据,需要根据用户的status字段(值为active或inactive)来显示不同颜色的标签。
数据示例
假设传入模板的数据结构如下:
const userData = {
users: [
{ name: "张三", status: "active" },
{ name: "李四", status: "inactive" },
{ name: "王五", status: "active" }
]
};模板实现
使用<if>判断状态值,动态输出对应的CSS类名:
<ul class="user-list">
{{#each users}}
<li class="user-item {{#if (eq status 'active')}}active-user{{else}}inactive-user{{/if}}">
<span class="user-name">{{name}}</span>
<span class="user-status">{{status}}</span>
</li>
{{/each}}
</ul>这里用到了eq自定义助手,用于判断两个值是否相等,需要先注册该助手:
Handlebars.registerHelper('eq', function(a, b) {
return a === b;
});对应CSS样式
.user-list {
list-style: none;
padding: 0;
}
.user-item {
padding: 12px 16px;
margin-bottom: 8px;
border-radius: 4px;
border: 1px solid #e5e5e5;
}
.active-user {
background-color: #f0f9eb;
border-color: #e1f3d8;
color: #67c23a;
}
.inactive-user {
background-color: #fef0f0;
border-color: #fde2e2;
color: #f56c6c;
}进阶场景:多条件动态样式
当需要根据多个数据字段的组合判断样式时,可以注册更复杂的自定义助手。比如订单列表需要根据type(订单类型)和amount(订单金额)两个字段,为不同类型和金额的订单应用不同样式。
数据示例
const orderData = {
orders: [
{ id: "O001", type: "normal", amount: 120 },
{ id: "O002", type: "vip", amount: 300 },
{ id: "O003", type: "normal", amount: 80 },
{ id: "O004", type: "vip", amount: 150 }
]
};自定义多条件助手
注册一个orderClass助手,根据订单类型和金额返回对应的样式类:
Handlebars.registerHelper('orderClass', function(type, amount) {
if (type === 'vip' && amount >= 200) {
return 'vip-high-amount';
} else if (type === 'vip' && amount < 200) {
return 'vip-low-amount';
} else if (type === 'normal' && amount >= 100) {
return 'normal-high-amount';
} else {
return 'normal-low-amount';
}
});模板实现
<table class="order-table">
<thead>
<tr>
<th>订单ID</th>
<th>订单类型</th>
<th>订单金额</th>
</tr>
</thead>
<tbody>
{{#each orders}}
<tr class="{{orderClass type amount}}">
<td>{{id}}</td>
<td>{{type}}</td>
<td>{{amount}}元</td>
</tr>
{{/each}}
</tbody>
</table>对应CSS样式
.order-table {
width: 100%;
border-collapse: collapse;
}
.order-table th, .order-table td {
padding: 12px 16px;
border: 1px solid #e5e5e5;
text-align: left;
}
.vip-high-amount {
background-color: #fdf6ec;
color: #e6a23c;
font-weight: bold;
}
.vip-low-amount {
background-color: #fdf6ec;
color: #e6a23c;
}
.normal-high-amount {
background-color: #ecf5ff;
color: #409eff;
}
.normal-low-amount {
background-color: #f4f4f5;
color: #909399;
}特殊场景:动态内联样式
如果样式的属性值需要根据数据动态计算(比如进度条的宽度、元素的透明度等),可以直接在style属性中嵌入Handlebars表达式,动态生成内联样式。
比如根据任务的完成进度progress(0-100的数值)动态设置进度条的宽度:
数据示例
const taskData = {
tasks: [
{ name: "需求评审", progress: 100 },
{ name: "开发实现", progress: 65 },
{ name: "测试验证", progress: 20 }
]
};模板实现
<div class="task-list">
{{#each tasks}}
<div class="task-item">
<div class="task-name">{{name}}</div>
<div class="progress-bar">
<div class="progress-inner" style="width: {{progress}}%"></div>
</div>
<div class="progress-text">{{progress}}%</div>
</div>
{{/each}}
</div>对应CSS样式
.task-list {
width: 400px;
}
.task-item {
margin-bottom: 16px;
}
.task-name {
margin-bottom: 8px;
font-size: 14px;
}
.progress-bar {
height: 12px;
background-color: #e5e5e5;
border-radius: 6px;
overflow: hidden;
}
.progress-inner {
height: 100%;
background-color: #409eff;
border-radius: 6px;
transition: width 0.3s ease;
}
.progress-text {
margin-top: 4px;
font-size: 12px;
color: #666;
text-align: right;
}注意事项
自定义助手需要先注册再使用,否则模板渲染时会报错
如果条件判断逻辑过于复杂,建议将样式类的计算逻辑放在数据预处理阶段,或者在自定义助手中实现,避免模板过于臃肿
动态生成内联样式时,需要确保数据值的合法性,避免出现无效的CSS属性值
如果需要判断的条件较多,也可以使用
<switch>类的自定义助手,简化多分支判断的模板语法