Sparkline在Layui表格中渲染失败主因是DOM未挂载完成即初始化;需在table.render的done回调中用requestAnimationFrame延迟遍历.sparkline-cell单元格,清空旧canvas后插入新canvas并调用sparkline(),同时每次重绘前清除旧实例。
Sparkline 图表在 Layui 表格中渲染失败的常见原因
直接在 layui.table.render() 的 cols 配置里用 templet 插入 <canvas></canvas> 或调用 sparkline(),大概率会白屏、报错或只显示第一个单元格——因为 layui 渲染表格时是批量生成 dom,而多数 sparkline 库(如 jquery.sparkline)依赖元素已挂载到文档流且尺寸可读。表格滚动、分页、重绘时,未做生命周期管理的图表会丢失或重复初始化。
用 done 回调 + 延迟绑定渲染 Sparkline
必须等表格 DOM 完全就绪、且每行数据都已插入页面后,再逐个查找目标单元格并初始化图表。不能在 templet 里直接 new 实例。
-
done回调里用setTimeout(..., 0)或requestAnimationFrame确保 DOM 已 flush,再遍历.layui-table-body .layui-table-cell中带特定 class(比如sparkline-cell)的单元格 - 每个单元格内先清空旧
<canvas></canvas>(避免重复渲染叠加),再插入新<canvas></canvas>并调用$(...).sparkline() - 数据需从原始行对象提取,不要依赖单元格 innerHTML —— 表格可能含 HTML 转义或格式化内容
done: function(res, curr, count) {
requestAnimationFrame(() => {
$('.sparkline-cell').each(function() {
const $cell = $(this);
const data = $cell.data('values'); // 提前存好数组,如 [12, 19, 11, 29, 15]
$cell.empty().append('<canvas></canvas>');
$cell.find('canvas').sparkline(data, {
type: 'line',
width: '80px',
height: '24px',
lineColor: '#39f',
fillColor: 'rgba(57,159,255,0.1)'
});
});
});
}
兼容 Layui 分页/搜索/排序后的图表重绘
每次表格重载(table.reload())、搜索、排序都会触发 done,但默认不会清除旧图表实例,导致内存泄漏和 canvas 重叠。必须主动销毁。
- 在
done开头加$('.sparkline-cell canvas').remove();清理上一轮画布 - 避免用全局变量存图表实例;若需交互(如 hover 显示数值),改用事件委托绑定到父容器,监听
canvas上的mousemove - 移动端要注意
canvas像素比,sparkline默认不处理 devicePixelRatio,小图可能模糊 —— 可手动缩放 canvas.width/height 并用 CSS 缩放回原尺寸
替代方案:纯 CSS + SVG 的轻量 Sparkline(无 JS 依赖)
如果只是展示趋势线、不需要交互或动态更新,用 SVG path 替代 canvas 更稳。Layui 表格支持在 templet 中直接返回 SVG 字符串,且不受 DOM 挂载时机限制。
- 预计算折线路径:把 5~10 个数值归一化为 0–100 区间,映射成
<path d="M0,80 L20,60 L40,70..."></path> - 用
viewBox控制缩放,CSS 设定固定宽高,确保不同分辨率下清晰 - 缺点:无法响应式重绘,数据变化需重新渲染整行;但省去 JS 初始化开销,适合只读报表场景
复杂点在于数值归一化逻辑要写在 templet 函数里,且得避开 Layui 对 HTML 字符串的自动转义 —— 必须用 return {html: svgStr} 形式(部分 Layui 版本需升级到 2.9+)。











