场景描述
bootstrap 列表加载图片时需要同时获取图片的像素(宽 and 高),对于腾讯云这类远程存储获取图片来说,虽然也可以通过 java 后台调用腾讯云接口获取图片像素,但是在列表加载大量图片并且没有分页的情况下,如果通过后台逐个获取图片像素信息返回给前台页面渲染的话,会导致前台页面迟迟加载不出来,且有浏览器内存耗尽卡死的风险,并且腾讯云获取图片像素信息的接口还有频限 100 的限制,这就更导致了通过后台获取图片像素方案的不适用,那么如果通过页面 jquery 获取图片像素的时候当图片量很大的时候也是会出现卡顿,加载慢的情况,这个时候就考虑的热区内图片展示像素,非热区内图片待鼠标下滑啊时再加载像素信息方案的产生。
问题处理
基于上面的需求场景,那么就想到了 jquery 的 scroll()方法的加载结构和页面热区的宽高计算,然后补充具体参数信息及业务逻辑信息
列表 html 结构如下
页面 js 源码如下
var start = function() {
var imgs = $('.bootstrap-table tbody>tr').not('.dataloaded'); // 选择出未加载的图片
if (imgs.length) {
// 遍历循环
$.each(imgs, function (k, y) {
var _this = $(this), _o = _this.offset().top, _h = $('#tableDiv').scrollTop() + $('.search-collapse').height() + $('#tableDiv').height();
// 可视区判断
if (_o <= _h) {
var filenameobj = _this.find("td:eq(1)");
var fileType = _this.find("td:eq(3)").text();
// 加载图片,并标记
loadImg(_this);
if (fileType != "-" && ("jpg" == fileType.toLowerCase() || "png" == fileType.toLowerCase() ||
"gif" == fileType.toLowerCase() || "jpeg" == fileType.toLowerCase())) {
var path = $("#title").val();
var imgurl = domain+path+filenameobj.find('a').attr('title');
var img = new Image(); img.src = imgurl;
if (img.complete) {
var _w = img.width, _h = img.height;
var text = filenameobj.text();
var text2 = text+"("+_w+"*"+_h+")";
filenameobj.find('a').find('span').text(text2);
}else {
img.onload = function () {
var _w = img.width, _h = img.height;
var text = filenameobj.text();
var text2 = text+"("+_w+"*"+_h+")";
filenameobj.find('a').find('span').text(text2);
}
}
//console.log("start()======"+filenameobj.find('a').find('span').text());
}
} else { // ps:超出可视区外的图片不再循环,防止资源消耗过多
return false;
}
})
} else {
// 所有图片都已加载,禁止事件监听
$('#tableDiv').off('scroll');
}
}
function loadImg($img) {
//$img.attr('src', $img.attr('data-src'));
$img.addClass('dataloaded');
}
复制代码
其中,在 bootstrap 列表加载增加 onLoadSuccess() 待列表加载完成之后执行 start()方法给热区内 img 赋值像素
function onLoadSuccess(res){
start();
// 绑定 scroll 事件,用于监听元素是否进入可视区
$('#tableDiv').scroll(function () {
start();
})
}
复制代码
效果如图
初始化列表时执行一次 start(),给热区内图片赋值像素,待滚动鼠标时再拉去当前页面热区内未加载图片像素信息的图片像素
其他问题处理
由于业务需要,除了列表页,我们同时增加了视图模式,效果如图
列表增加了滚动加载图片像素信息的方法,那么视图模式同样也需要,视图代码结构
增加 start1()方法用于针对视图模式处理
var start1 = function() {
var imgs = $('.trdata').not('.dataloaded'); // 选择出未加载的图片
//console.log("----------run-------------------"+imgs.length)
if (imgs.length) {
// 遍历循环
$.each(imgs, function (k, y) {
var _this = $(this), _o = _this.offset().top, _h = $('#tableDiv').scrollTop() + $('.search-collapse').height() + $('#tableDiv').height();
// 可视区判断
if (_o <= _h) {
var textcenterdivobj = _this.find("div:eq(1)").find("a").find("div");
//console.log("111"+textcenterdivobj.html());
var img = textcenterdivobj.find("img");
var fileType = img.attr("data-type");
//console.log("222"+fileType);
// 加载图片,并标记
loadImg(_this);
if (fileType != undefined && fileType != "-" && ("jpg" == fileType.toLowerCase() || "png" ==
fileType.toLowerCase() ||
"gif" == fileType.toLowerCase() || "jpeg" == fileType.toLowerCase())) {
var imgurl = img.attr("src");
//console.log("333"+imgurl);
var namediv = textcenterdivobj.find("div").find("div");
var text = namediv.text();
var img = new Image(); img.src = imgurl;
if (img.complete) {
var _w = img.width, _h = img.height;
var text2 = text+"("+_w+"*"+_h+")";
namediv.text(text2);
}else {
img.onload = function () {
var _w = img.width, _h = img.height;
var text2 = text + "(" + _w + "*" + _h + ")";
namediv.text(text2);
}
}
//console.log("start1()======"+namediv.text());
}
} else { // ps:超出可视区外的图片不再循环,防止资源消耗过多
return false;
}
})
} else {
// 所有图片都已加载,禁止事件监听
$('#tableDiv').off('scroll');
}
}
复制代码
视图模式的加载效果
既然加了视图模式,那么就会涉及到视图和列表切换时方法的销毁问题,因为不销毁的话,在列表模式下,滚动的话也会执行视图模式的滚动方法导致资源浪费,关闭滚动方法的处理如下
//切换列表和块的方法
function toggleCustomView(){
if($('#customViewDiv').is(':hidden')){
$(window).off('scroll',start);
start1();
// 绑定 scroll 事件,用于监听元素是否进入可视区
$('#tableDiv').scroll(function () {
start1();
})
$('#customViewDiv').show();
$('#bootstrap-table').hide();
}else{
$(window).off('scroll',start1);
$('#tableDiv').scroll(function () {
start();
})
$('#customViewDiv').hide();
$('#bootstrap-table').show();
}
}
复制代码
如此的话就解决了问题也没有导致资源重复加载。
评论