使用Print.js打印Local Storage中JSON收支数据遇问题求助
解决Print.js无法正确打印LocalStorage中嵌套JSON数据的问题
问题根源分析
你遇到的问题主要来自两个点:
- 最初未解析LocalStorage的字符串数据,导致Print.js无法识别有效JSON结构,抛出
Missing printable information错误。 - 解析后的数据是嵌套对象结构(
{income: {...}, outgoings: {...}}),而Print.js的type: 'json'模式默认期望接收数组类型的可打印数据,直接传入嵌套对象无法正确渲染内容。
你的LocalStorage数据里,income和outgoings都是以数字为键的对象集合,需要先转换成数组才能被Print.js正确处理;如果要实现美观的打印格式,推荐使用Print.js的HTML打印模式,自定义排版和样式会更灵活。
解决方案代码实现
1. 先修正数据获取与转换逻辑
首先确保从LocalStorage拿到的是解析后的JS对象,再把嵌套的对象集合转换成数组:
// 从LocalStorage获取并解析数据 const getExpensesData = () => { const storedData = localStorage.getItem('my_expenses'); return storedData ? JSON.parse(storedData) : {}; }; // 将嵌套的对象集合转换为数组 const formatExpensesToArray = (expensesObj) => { return { income: Object.values(expensesObj.income || {}), outgoings: Object.values(expensesObj.outgoings || {}) }; };
2. 构建美观的HTML打印模板
使用Print.js的type: 'html'模式,自定义打印内容的布局和样式,实现更专业的打印效果:
function printExpenses() { const rawData = getExpensesData(); const { income, outgoings } = formatExpensesToArray(rawData); // 构建打印用的HTML内容 const printContent = ` <div style="max-width: 800px; margin: 0 auto; font-family: Arial, sans-serif;"> <h1 style="text-align: center; color: #2c3e50;">My Expenses Summary</h1> <!-- 收入部分 --> <div style="margin-top: 30px;"> <h2 style="color: #27ae60;">Income</h2> <table style="width: 100%; border-collapse: collapse; margin-top: 10px;"> <thead> <tr style="background-color: #ecf0f1;"> <th style="border: 1px solid #bdc3c7; padding: 10px; text-align: left;">Name</th> <th style="border: 1px solid #bdc3c7; padding: 10px; text-align: left;">Frequency</th> <th style="border: 1px solid #bdc3c7; padding: 10px; text-align: left;">Value</th> </tr> </thead> <tbody> ${income.map(item => ` <tr> <td style="border: 1px solid #bdc3c7; padding: 10px;">${item.name}</td> <td style="border: 1px solid #bdc3c7; padding: 10px;">${item.freq}</td> <td style="border: 1px solid #bdc3c7; padding: 10px;">${item.value}</td> </tr> `).join('')} </tbody> </table> </div> <!-- 支出部分 --> <div style="margin-top: 30px;"> <h2 style="color: #e74c3c;">Outgoings</h2> <table style="width: 100%; border-collapse: collapse; margin-top: 10px;"> <thead> <tr style="background-color: #ecf0f1;"> <th style="border: 1px solid #bdc3c7; padding: 10px; text-align: left;">Name</th> <th style="border: 1px solid #bdc3c7; padding: 10px; text-align: left;">Frequency</th> <th style="border: 1px solid #bdc3c7; padding: 10px; text-align: left;">Value</th> </tr> </thead> <tbody> ${outgoings.map(item => ` <tr> <td style="border: 1px solid #bdc3c7; padding: 10px;">${item.name}</td> <td style="border: 1px solid #bdc3c7; padding: 10px;">${item.freq}</td> <td style="border: 1px solid #bdc3c7; padding: 10px;">${item.value}</td> </tr> `).join('')} </tbody> </table> </div> </div> `; // 调用Print.js打印 printJS({ printable: printContent, type: 'html', style: '@page { margin: 1cm; }', // 调整打印页边距 scanStyles: false // 禁用自动扫描页面样式,使用自定义样式 }); }
3. 修改按钮的点击事件
把原来的按钮点击事件替换为我们自定义的函数:
<button type="button" onclick="printExpenses()">Print Expenses Summary</button>
备选方案:直接用JSON模式打印
如果你更倾向于使用Print.js的JSON模式,可以单独打印收入或支出数组:
function printIncomeOnly() { const rawData = getExpensesData(); const incomeArray = Object.values(rawData.income || {}); printJS({ printable: incomeArray, properties: ['name', 'freq', 'value'], type: 'json', header: 'Income Details', gridHeaderStyle: 'background-color: #27ae60; color: white;', gridStyle: 'border: 1px solid #bdc3c7;' }); }
内容的提问来源于stack exchange,提问作者Brian Revie
相关产品推荐
相关产品推荐

