HTML表格本身不渲染数据,需依赖模板引擎执行变量替换、转义及空值处理;Jekyll/Hugo中常见空列、错位或[object Object]问题,根源在于YAML解析错误、模板语法误用或路径引用不当,Eleventy通过预处理数据结构可规避模板逻辑复杂性与XSS风险。

HTML表格本身不渲染数据,静态网站生成器(SSG)里也一样——它只输出结构,数据得靠模板引擎塞进去。你写 <table><tr><td>{{ item.name }}</td></tr></table>,最终能否正确显示,取决于模板引擎是否执行了变量替换、是否转义、是否处理了空值或嵌套结构。
为什么 Jekyll/Hugo 中的表格常出现空行或错位
常见现象是:本地预览正常,部署后某列全空;或 {{ page.data }} 渲染成 [object Object];或 YAML 数组被当成字符串拼进 <td> 里。
- YAML 中的列表若没缩进对齐,会被解析成字符串而非数组,导致
for循环不触发 - Hugo 的
.Params.items若定义为items: ["a", "b"],模板中必须用{{ range .Params.items }},不能直接{{ .Params.items }} - Jekyll 的 Liquid 模板对空值默认输出空字符串,但若字段根本不存在(比如
page.author缺失),{{ page.author }}会留白,而{{ page.author | default: "未知" }}才安全 - 表格列数不一致时(比如某行少一个
<td>),浏览器自动补<td>,但位置不可控,视觉错位
Eleventy 中用 renderData 控制表格内容生成时机
Eleventy 的优势在于能提前把原始数据加工成表格所需格式,避免模板里写逻辑。比如原始 Markdown front matter 是扁平对象,但表格需要二维数组:
---
title: 成绩表
students:
- name: 张三
math: 85
english: 92
- name: 李四
math: 76
english: 88
---在 .eleventy.js 中加计算属性:
立即学习“前端免费学习笔记(深入)”;
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
eleventyConfig.addCollection("scoreTable", function(collection) {
return collection.getFilteredByTag("score").map(page => ({
...page,
tableRows: page.data.students.map(s => [s.name, s.math, s.english])
}));
});模板里就直接用 {{ page.tableRows }} 渲染,不用在 Njk 或 Liquid 里做 map/filter —— 减少模板复杂度,也避免 XSS 风险(因为数据已结构化,不拼 HTML 字符串)。
VuePress/VitePress 中 v-for 渲染表格要防 key 错乱
在 VuePress 的 Markdown 文件里嵌入 Vue 组件时,容易忽略 key 必须唯一且稳定。比如这样写:
<template>
<table>
<tbody>
<tr v-for="(row, i) in data" :key="i">
<td>{{ row.name }}</td>
<td>{{ row.score }}</td>
</tr>
</tbody>
</table>
</template>当数据按 score 排序后,i 不再对应原始索引,Vue 会复用旧 DOM 节点,导致姓名和分数错位。正确做法是用业务字段(如 row.id)或哈希值作 key:
- 确保数据源有唯一标识字段(如
id或name + timestamp组合) - 避免用
Math.random()或Date.now()生成 key,会导致每次重渲染都重建节点 - 如果数据无 ID,可用
JSON.stringify(row)作 key(仅限小数据量,性能差)
真正麻烦的不是“怎么让表格显示出来”,而是“怎么让表格在数据变更、排序、筛选后仍保持语义正确和 DOM 稳定”。SSG 生成的是快照,但用户看到的页面可能被 JS 动态修改——这两层渲染逻辑一旦脱节,错位、丢失状态、XSS 就都来了。


















