Skip to content

指南 · 基础

版本基线 3.x。本篇把「会填一个值」升级到「懂标签与作用域」:标签类型全览、区块的循环/条件双重身份、作用域如何切换、默认解析器的局限与 expressions 解析器、缺值处理。

一、四类标签一览

写法名字干什么
{name}占位符取数据里的 name 填进去
{#list}…{/list}区块数组→循环;真值→条件
{^list}…{/list}反向区块falsy(空/false/null)时才渲染
{@xml}raw XML插入一段原始 OOXML(不转义)

还有两个常用辅助:{.} 取「当前元素本身」(原始值数组用),{/} 闭合「最近打开的区块」(省名字)。

二、区块:循环与条件是同一个东西

docxtemplater 的精妙之处:区块标签根据数据类型自动切换身份。

text
{#users}{name}{/users}
  • users数组 → 中间内容对每个元素重复(循环),作用域切到当前元素。
  • users真值(对象/true/非空字符串)→ 中间内容渲染一次(条件成立)。
  • usersfalsy(false/null/空数组)→ 中间内容不渲染

配套的反向区块 {^users} 正好相反:仅当 falsy 时渲染,常用来写「没有数据时的提示」。

text
{#orders}你有 {.length} 个订单{/orders}
{^orders}暂无订单{/orders}

三、作用域:循环内的 {name} 是谁

区块会把作用域(scope)下沉到当前元素。看这个例子:

text
公司:{company}
{#staff}
  - 姓名:{name}(部门:{dept})
{/staff}
ts
doc.render({
  company: 'ACME',
  staff: [
    { name: '张三', dept: '研发' },
    { name: '李四', dept: '市场' },
  ],
});
  • 循环外 {company} 取顶层的 company
  • 循环内 {name}{dept}当前 staff 元素的属性,不是顶层。
  • 若当前元素没有某属性,docxtemplater 会向上回溯到父作用域查找。

原始值数组(如 ['a','b','c'])的元素没有属性名,循环里用 {.} 取元素本身:{#tags}{.} {/tags}a b c

四、默认解析器的「天花板」

这是新手最容易栽的地方。默认解析器只做简单属性查找

text
{user.name}   ← 被当成查找字面键名 "user.name",而不是 user → name
{price + tax} ← 不会做加法,当成怪异键名
{n > 1}       ← 不支持比较

默认解析器不会报编译错误,只是默默取不到值(渲染成 undefined),更隐蔽。

五、expressions 解析器:解锁表达式

要支持点号、运算、比较、过滤器,启用免费的 expressions 解析器(基于 angular-expressions,随包提供):

ts
import expressionParser from 'docxtemplater/expressions.js';

const doc = new Docxtemplater(zip, {
  parser: expressionParser,
  paragraphLoop: true,
  linebreaks: true,
});

启用后这些都能用:

text
{user.name}                嵌套属性
{price + tax}              算术
{#users.length > 1}多人{/} 比较 + 条件区块
{vip ? '尊享' : '普通'}     三元
{name | upper}             过滤器(需 configure 注册)
{#items}{$index}: {.}{/items}  下标 $index

{/} 在这里很实用:长表达式区块 {#users.length > 1}…{/} 结尾不必重写整个表达式。

六、注册过滤器

过滤器要先通过 configure 注册再用管道 | 调用:

ts
import expressionParser from 'docxtemplater/expressions.js';

expressionParser.configure({
  filters: {
    upper: (input) => (input == null ? input : String(input).toUpperCase()),
    round: (input, digits = 0) => Number(input).toFixed(digits),
  },
});
// 模板:{name | upper}   {price | round:2}

七、缺值:默认是字面 "undefined"

普通标签取不到值时,默认渲染成字面字符串 undefined(不是空串!)。要改成空串或占位文案,用 nullGetter

ts
const doc = new Docxtemplater(zip, {
  nullGetter() {
    return ''; // 缺值统一显示为空
  },
});

raw XML 标签 {@xml} 缺值时默认是空串。


进入 指南 · 进阶:表格行循环、异步数据 renderAsync、浏览器下载、服务端返回文件、错误聚合处理。