如何使用不同数据集多次调用docxtemplater.render()且避免标签变为undefined
问题解决方案
最优方案(推荐)
你不需要重新从云端拉取Word文档,只需要把首次拉取到的文档二进制数据缓存到内存中即可,操作逻辑如下:
- 拉取云端Word文档后,把原始二进制数据存为变量缓存
- 用缓存的二进制创建第一个带
InspectModule的docxtemplater实例,调用render()收集所有标签,这个实例用完即可丢弃 - 拿到标签请求后端接口获取替换数据后,再用之前缓存的原始二进制创建新的docxtemplater实例,传入数据直接渲染即可
这个方案实现最简单,内存开销极低,完全规避了实例状态被修改的问题,也不需要深拷贝实例或者寻找不存在的reset()方法,是官方推荐的标准处理逻辑。
对应优化后的代码示例
// 1. 拉取文档并缓存原始二进制数据 const originDocData = await fetch("something.docx"); // 2. 第一次创建实例收集标签 const iModule = InspectModule(); const inspectZip = new PizZip(originDocData); const inspectDoc = new Docxtemplater(inspectZip, {modules: [iModule]}); inspectDoc.render(); const tags = Object.keys(iModule.getAllTags()); // 3. 请求你的后端接口拿到替换数据 const myData = await fetchYourApi(tags); // 4. 第二次用缓存的原始数据创建实例渲染 const renderZip = new PizZip(originDocData); const renderDoc = new Docxtemplater(renderZip); renderDoc.setData(myData); renderDoc.render(); // 后续导出渲染后的文档即可 const resultBuffer = renderDoc.getZip().generate({type: "nodebuffer"});
其他可选方案
如果确实想要复用同一个实例,可以在初始化实例的时候配置nullGetter参数,让第一次渲染时标签不会被替换为undefined:
const document = new Docxtemplater(zip, { modules: [iModule], nullGetter: function(part) { // 直接返回原始的标签占位符,默认定界符为{},如果自定义过定界符需要对应调整 return `{${part.value}}`; } });
注意:这个方案依赖你的标签语法是默认的{变量名}格式,部分复杂语法(比如循环、条件标签)可能不生效,通用稳定性不如缓存原始数据的方案。
内容的提问来源于stack exchange,提问作者Mario Varchmin
相关产品推荐
相关产品推荐

