layui图片预览需手动调用layer.photos()并传入含data数组的相册对象,每项至少含src字段;推荐用data-src存高清图、click/touchstart双事件绑定、批量预览时预构建photoList数组。

点击图片触发 layui 的 layer.photos() 方法
layui 自带的图片预览功能依赖 layer.photos(),它不是自动绑定的,必须手动调用。常见错误是直接给 <img> 加 onclick 却没传符合要求的数据结构,结果点击无反应或报错 TypeError: Cannot read property 'length' of undefined。
关键点在于:你得构造一个符合 layer.photos 要求的「相册对象」,其中 data 字段必须是数组,且每个元素至少含 src(图片地址)字段。
- 最简可行做法:把当前图片包装成单图相册对象,传给
layer.photos() - 不要直接传
this.src或字符串,必须传完整对象:{data: [{src: this.src}]} - 如果页面有多张图,建议统一用
data-index和预加载的 JSON 数据做索引,避免重复解析 DOM
HTML 结构要带 data-src 或可靠来源
很多人把图片地址只写在 src 属性里,但缩略图可能被压缩/裁剪过,直接放大看不清。更稳妥的方式是用 data-src 存原始高清图地址,src 仅用于页面展示。
示例 HTML:
<img src="/thumb/1.jpg" class="preview-img"> <img src="/thumb/2.jpg" class="preview-img">
对应 JS 绑定:
$('.preview-img').on('click', function() {
var src = $(this).data('src') || $(this).attr('src');
layer.photos({
photos: {data: [{src: src}]},
shade: 0.7,
closeBtn: 1
});
});
批量图片预览需提前组织好 photos.data 数组
如果你有一组图片想支持左右切换预览,就不能每张图单独传单图对象——那样切换时会丢失上下文。必须一次性把所有图的 src(推荐也带上 alt)收集进数组,再传给 layer.photos()。
- 数组顺序决定预览时的左右顺序,别靠 DOM 顺序动态取,容易错乱
- 避免在点击时实时查 DOM 拼数组(性能差、易漏),推荐初始化时就构建好全局变量或存到父容器的
data - 注意路径问题:如果
data-src是相对路径,确保和当前页面同域且可访问,否则预览时显示“加载失败”
例如初始化时收集:
var photoList = $('.gallery img').map(function() {
return {src: $(this).data('src') || $(this).attr('src')};
}).get();
然后绑定点击事件时指定初始索引:
$('.gallery img').on('click', function() {
var index = $('.gallery img').index(this);
layer.photos({
photos: {data: photoList},
start: index
});
});
移动端点击放大失效?检查 touchstart 和 fastclick 冲突
在 iOS 或部分安卓 WebView 中,单纯监听 click 可能有 300ms 延迟甚至不触发,尤其用了 fastclick 或其他触摸库时,click 事件可能被屏蔽或延迟派发。
- 临时验证方法:把事件换成
touchstart,但注意加e.preventDefault()防止滚动干扰 - 更稳方案:用
layer.open()手动实现放大层,配合img标签 +max-width: 100%+transform: scale(),可控性更强 - layui 2.8+ 对 touch 支持有所增强,但如果项目用了老版本(如 2.5.6),优先升级 layer 或降级处理事件绑定
简单兼容写法:
$('.preview-img').on('click touchstart', function(e) {
e.preventDefault();
var src = $(this).data('src') || $(this).attr('src');
layer.photos({photos: {data: [{src: src}]}});
});
真正麻烦的是混合缩放与下载需求——比如想在预览时加个下载按钮,但 layer.photos 默认不提供 DOM 入口;这时候就得放弃封装方法,改用 layer.open() 自定义内容,否则后期维护成本会突然升高。


















