直接在templet中生成二维码会因表格重渲染导致DOM重复绑定、canvas覆盖等问题;应改用done回调批量初始化,通过data属性关联数据与二维码,并用事件委托实现点击放大与下载。
为什么直接用 layui.table.render() 的 templet 渲染二维码会失败
常见错误是把二维码生成逻辑写在 templet 里,每次渲染都调用 qrcode.js 或类似库的构造函数,但 layui 表格在分页、排序、重载时会反复执行 templet,导致 dom 节点重复绑定、canvas 元素被覆盖、事件丢失——最终点击无反应或只放大第一个单元格。
根本原因:Layui 表格的 templet 是纯字符串/函数返回值,不保证节点生命周期可控;而二维码需要真实 DOM 节点 + 事件委托 + 图片缓存/复用。
- 不要在
templet中直接 new QRCode(...),避免 canvas 多次插入 - 不要给每个二维码单独绑
click,要用事件委托到表格容器 - 二维码图片建议转为
data:image/png;base64字符串预生成,避免重复绘制
用 templet 只放占位元素,二维码生成延后到 done 回调中
done 是表格首次渲染完成后的唯一稳定时机,此时所有 tr 已挂载,可安全遍历并批量初始化二维码。关键是要用唯一标识(如数据中的 id 或行索引)关联单元格与二维码实例。
layui.table.render({
elem: '#demo',
url: '/api/list',
cols: [[
{field: 'id', title: 'ID'},
{field: 'sn', title: '序列号', templet: '<div class="qrcode-cell" data-sn="{{d.sn}}"></div>'},
]],
done: function(res, curr, count) {
// 批量生成二维码并绑定点击
$('.qrcode-cell').each(function() {
const $cell = $(this);
const sn = $cell.data('sn');
if (!sn || $cell.find('img').length) return; // 避免重复生成
// 生成 base64 二维码(推荐用 qrcode-generator 或 tinyqrcode)
const qrData = QRCode.generateSVG(sn, { width: 80, height: 80 }); // SVG 更清晰
const $img = $(`<img src="${qrData}" class="qrcode-img" alt="QR">`);
$cell.empty().append($img);
});
}
});
如何实现点击放大并支持关闭和下载
放大不能用简单 alert 或 layer.msg,需一个轻量弹层。Layui 自带 layer.photos 不适用(它依赖图片数组),所以用 layer.open + 手动传入大图 src 最可靠。
- 给所有二维码
img统一加class="qrcode-img" - 用事件委托绑定
click到表格容器(防止动态插入的 img 无法捕获) - 放大图尺寸设为 300×300,足够扫码;同时提供右键「图片另存为」能力
// 表格外层容器假设是 #demo-table
$('#demo-table').on('click', '.qrcode-img', function(e) {
e.stopPropagation();
const src = this.src.replace(/width=\d+&height=\d+/g, 'width=300&height=300');
layer.open({
type: 1,
title: false,
closeBtn: 1,
area: ['320px', '320px'],
skin: 'layui-layer-nobg', // 透明背景
shadeClose: true,
content: `<div style="text-align:center;padding:20px;"><img src="${src}" style="max-width:100%;max-height:260px;"></div>`
});
});
移动端扫码体验差?必须加 user-scalable=no 和缩放适配
很多用户反馈在 iOS Safari 点击放大后无法双指缩放查看细节,或者二维码模糊——本质是 viewport 缩放被禁用或图片未按设备像素比渲染。
- 确保页面
<meta name="viewport">包含user-scalable=yes(哪怕只是临时放开) - 生成二维码时传入
scale: window.devicePixelRatio || 2(如果用 qrcode.js) - 放大弹层里的
img加style="image-rendering: -webkit-optimize-contrast;"提升清晰度
最省事的兼容方案:改用 SVG 二维码(如 qrcode-generator 的 generateSVG),矢量图在任意缩放下都清晰,且无需处理 DPR。


















