直接用 layer.photos 配合事件委托实现图片预览,须避开三坑:templet 内联 onclick 失效(因表格动态渲染导致绑定丢失)、不可单独绑定事件、photos 结构必须为 {photos: {data: [...]}};正确做法是在 done 回调中用 layui.$ 对 .layui-table-box 委托绑定 click 事件,并每次先 off 再 on 防重复。
直接用 layer.photos 配合事件委托就能实现,但必须避开三个典型坑:不能在 templet 里写 onclick,不能对每张图单独绑定事件,不能传错 photos 结构。
为什么 templet 里写 onclick 会失效
Layui 表格是动态渲染的——翻页、重载、搜索后 DOM 全部重建。写在 templet 里的 onclick="showImg('{{d.avatar}}')" 本质是内联 JS,每次重新渲染都会丢掉旧绑定,新生成的 img 没有事件;更糟的是,如果用了分页或开启 page: true,首次加载后点击可能根本没反应。
正确做法是把事件监听完全交给 done 回调 + 事件委托:
- 用
layui.$('#demo').next('.layui-table-box').on('click', '.layui-table-img', ...)绑定到滚动容器上 - 不要用原生
document.querySelector或$(jQuery),layui.$才能穿透虚拟滚动区域 - 类名如
.layui-table-img必须统一,别用随机 ID 或行级 class
layer.photos 的参数结构必须严格符合要求
layer.photos 不接受字符串或数组,只认 {photos: {data: [...]}} 这个嵌套结构。常见报错 Cannot read property 'length' of undefined 就是因为传了 layer.photos({src: 'xxx.jpg'}) 或 layer.photos(['xxx.jpg'])。
单图预览的最小合法调用是:
layer.photos({
photos: {
data: [{src: src}]
},
anim: 5
});
注意以下几点:
-
src字段必须存在且为非空字符串,否则预览空白 - 如果后端返回
null、''或about:blank,要提前过滤:if (!src || src.indexOf('about:') === 0) return; - 相对路径(如
/upload/1.jpg)需确保当前页面可跨域访问,否则控制台静默失败
表格翻页/重载后事件丢失怎么办
表格重绘时,.layui-table-box 内容会整个替换,之前绑定的事件自然消失。所以绝不能在 render 外部用 $(...).on(...),也不能在 templet 中用 each() 遍历绑定。
唯一可靠的方式是:每次 done 触发时,先解绑再重绑(防重复):
done: function(res, curr, count){
var $box = layui.$('#demo').next('.layui-table-box');
$box.off('click', '.layui-table-img');
$box.on('click', '.layui-table-img', function(){
var src = this.src;
if (!src || src.indexOf('about:') === 0) return;
layer.photos({
photos: {data: [{src: src}]},
anim: 5
});
});
}
这个模式覆盖所有场景:初始加载、翻页、reload、搜索重绘。
最易被忽略的一点:图片列模板中必须加 class(如 class="layui-table-img"),且这个 class 不能和表格其他元素冲突;一旦用错选择器,事件委托就查无此“人”。











