mirror of
https://gitee.com/layui/layui.git
synced 2025-12-27 06:35:47 +08:00
refactor(flow): 使用 component 模块重构组件 (#2860)
* refactor(flow): 使用 component 模块重构组件 * test(flow): 优化测试用例 * feat(component): 新增 index 实例成员 * fix(flow): 修复特殊场景下的事件冲突 * fix(flow): update
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
title: 流加载 flow
|
||||
toc: true
|
||||
---
|
||||
|
||||
|
||||
# 流加载
|
||||
|
||||
> 流加载 `flow` 是用于在*信息流*和*图片列表*场景中的滚动按需加载,对前后端的体验和性能优化具有一定帮助。
|
||||
@@ -26,6 +26,7 @@ toc: true
|
||||
| API | 描述 |
|
||||
| --- | --- |
|
||||
| var flow = layui.flow | 获得 `flow` 模块。 |
|
||||
| [基础接口](../component/#export) <sup>2.13+</sup> | 该组件由 `component` 构建,因此继承其提供的基础接口。|
|
||||
| [flow.load(options)](#load) | 信息流加载,核心方法。 |
|
||||
| [flow.lazyimg(options)](#lazyimg) | 图片懒加载。 |
|
||||
|
||||
@@ -74,7 +75,7 @@ toc: true
|
||||
<img lay-src="https://unpkg.com/outeres@0.0.11/demo/wallpaper.jpg">
|
||||
</div>
|
||||
|
||||
<!-- import layui -->
|
||||
<!-- import layui -->
|
||||
<script>
|
||||
layui.use('flow', function(){
|
||||
var flow = layui.flow;
|
||||
|
||||
@@ -1,92 +1,108 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>流加载 - layui</title>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>流加载 - layui</title>
|
||||
<link rel="stylesheet" href="../src/css/layui.css">
|
||||
<style>
|
||||
.flow-demo{height: 400px; overflow: auto;}
|
||||
.flow-default{margin-bottom: 32px; border: 1px solid #e2e2e2; text-align: center;}
|
||||
.flow-default li{display: inline-block; margin-right: 10px; width: 48%; margin-bottom: 10px; height: 200px; line-height: 200px; text-align: center; background-color: #eee;}
|
||||
.flow-default img{width: 100%; height: 100%; border: none;}
|
||||
.flow-default > img{width: 48%; height: 49%; margin-bottom: 5px;}
|
||||
</style>
|
||||
</head>
|
||||
<body class="layui-padding-3">
|
||||
<div class="flow-default flow-demo" id="ID-flow-demo"></div>
|
||||
<ul class="flow-default" id="test1"></ul>
|
||||
<div class="layui-hide">
|
||||
<ul class="flow-default" id="test2"></ul>
|
||||
</div>
|
||||
|
||||
<link rel="stylesheet" href="../src/css/layui.css">
|
||||
<div class="flow-default" style="height: 300px; overflow: auto;" id="ID-flow-lazyimg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
<img src="https://unpkg.com/outeres@0.2.0/img/other/loading.gif" lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg">
|
||||
</div>
|
||||
|
||||
<style>
|
||||
body{padding: 15px;}
|
||||
.flow-default{ font-size: 0;}
|
||||
.flow-default li{display: inline-block; margin-right: 10px; font-size: 14px; width: 48%; margin-bottom: 10px; height: 200px; line-height: 200px; text-align: center; background-color: #eee;}
|
||||
img{width: 500px; height: 300px;}
|
||||
.flow-default img{width: 100%; height: 100%;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script src="../src/layui.js"></script>
|
||||
<script>
|
||||
layui.use('flow', function() {
|
||||
var flow = layui.flow;
|
||||
|
||||
// 自动加载
|
||||
flow.load({
|
||||
elem: '#ID-flow-demo', // 流加载容器
|
||||
scrollElem: '#ID-flow-demo', // 滚动条所在元素,一般不用填,此处只是演示需要。
|
||||
done: function (page, next) {
|
||||
// 执行下一页的回调
|
||||
// 模拟数据插入
|
||||
setTimeout(function () {
|
||||
var lis = [];
|
||||
for (var i = 0; i < 8; i++) {
|
||||
lis.push('<li>' + ((page - 1) * 8 + i + 1) + '</li>');
|
||||
}
|
||||
|
||||
<ul class="flow-default" id="test1"></ul>
|
||||
// 执行下一页渲染,第二参数为:满足“加载更多”的条件,即后面仍有分页
|
||||
// pages 为 Ajax返回的总页数,只有当前页小于总页数的情况下,才会继续出现加载更多
|
||||
next(lis.join(''), page < 10); // 此处假设总页数为 10
|
||||
}, 300);
|
||||
},
|
||||
});
|
||||
|
||||
<div class="layui-hide">
|
||||
<ul class="flow-default" id="test2"></ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="demo" style="height: 300px; overflow: auto;">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/error.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
<img src="https://sentsin.gitee.io/res/images/demo/loading.gif" lay-src="https://sentsin.gitee.io/res/images/demo/layer.png">
|
||||
</div>
|
||||
|
||||
|
||||
<script src="../src/layui.js"></script>
|
||||
<script>
|
||||
layui.use('flow', function(){
|
||||
var flow = layui.flow;
|
||||
|
||||
flow.load({
|
||||
elem: '#test1' //流加载容器
|
||||
//,scrollElem: '.flow-default' //滚动条所在元素,默认document
|
||||
//,isAuto: false
|
||||
//,end: '没了'
|
||||
,isLazyimg: true
|
||||
,done: function(page, next){ //加载下一页
|
||||
console.log('done:', page)
|
||||
setTimeout(function(){
|
||||
var lis = [];
|
||||
for(var i = 0; i < 6; i++){
|
||||
lis.push('<li><img lay-src="https://sentsin.gitee.io/res/images/demo/layer.png?v='+ (page+i) +'"></li>')
|
||||
// 手动加载
|
||||
var flowInst = flow.load({
|
||||
elem: '#test1', // 流加载容器
|
||||
// scrollElem: '.flow-default', // 滚动条所在元素,默认 document
|
||||
// end: '没有更多数据',
|
||||
isAuto: false,
|
||||
isLazyimg: true,
|
||||
done: function(page, next) { // 加载下一页
|
||||
console.log('done:', page)
|
||||
setTimeout(function(){
|
||||
var lis = [];
|
||||
for(var i = 0; i < 6; i++){
|
||||
lis.push('<li><img lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg?v='+ (page+i) +'"></li>')
|
||||
}
|
||||
next(lis.join(''), page < 3);
|
||||
}, 300);
|
||||
}
|
||||
next(lis.join(''), page < 3);
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
flow.load({
|
||||
elem: '#test2' //流加载容器
|
||||
//,scrollElem: '.flow-default' //滚动条所在元素,默认document
|
||||
//,isAuto: false
|
||||
//,end: '没了'
|
||||
,isLazyimg: true
|
||||
,done: function(page, next){ //加载下一页
|
||||
setTimeout(function(){
|
||||
var lis = [];
|
||||
for(var i = 0; i < 6; i++){
|
||||
lis.push('<li><img lay-src="https://sentsin.gitee.io/res/images/demo/layer.png?v='+ (page+i) +'"></li>')
|
||||
// 重载
|
||||
flowInst.reload({
|
||||
moreText: '...'
|
||||
});
|
||||
|
||||
flow.load({
|
||||
elem: '#test2', // 流加载容器
|
||||
isLazyimg: true,
|
||||
done: function(page, next) { // 加载下一页
|
||||
setTimeout(function(){
|
||||
var lis = [];
|
||||
for(var i = 0; i < 6; i++){
|
||||
lis.push('<li><img lay-src="https://unpkg.com/outeres@0.2.0/demo/wallpaper.jpg?v='+ (page+i) +'"></li>')
|
||||
}
|
||||
next(lis.join(''), page < 3);
|
||||
}, 300);
|
||||
}
|
||||
next(lis.join(''), page < 3);
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//按屏加载图片
|
||||
flow.lazyimg({
|
||||
elem: '.demo img'
|
||||
,scrollElem: '.demo'
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
// 按屏加载图片
|
||||
flow.lazyimg({
|
||||
elem: '#ID-flow-lazyimg img',
|
||||
scrollElem: '#ID-flow-lazyimg',
|
||||
id: 'flow-lazyimg-demo'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -61,6 +61,7 @@ layui.define(['jquery', 'lay'], function(exports) {
|
||||
var inst = {
|
||||
config: options,
|
||||
id: id,
|
||||
index: that.index,
|
||||
|
||||
// 重置实例
|
||||
reload: function(options) {
|
||||
|
||||
@@ -1,205 +1,227 @@
|
||||
/**
|
||||
* flow 流加载组件
|
||||
* flow
|
||||
* 流加载组件
|
||||
*/
|
||||
|
||||
|
||||
layui.define(['i18n', 'jquery'], function(exports) {
|
||||
layui.define(['i18n', 'component'], function(exports) {
|
||||
"use strict";
|
||||
|
||||
var $ = layui.$;
|
||||
var i18n = layui.i18n;
|
||||
var Flow = function(options) {};
|
||||
var ELEM_MORE = 'layui-flow-more';
|
||||
var ELEM_LOAD = '<i class="layui-anim layui-anim-rotate layui-anim-loop layui-icon "></i>';
|
||||
|
||||
// 主方法
|
||||
Flow.prototype.load = function(options) {
|
||||
var that = this, page = 0, lock, isOver, lazyimg, timer;
|
||||
options = options || {};
|
||||
// 创建组件
|
||||
var component = layui.component({
|
||||
name: 'flow',
|
||||
|
||||
var elem = $(options.elem); if(!elem[0]) return;
|
||||
var scrollElem = $(options.scrollElem || document); // 滚动条所在元素
|
||||
var threshold = 'mb' in options ? options.mb : 50; // 临界距离
|
||||
var isAuto = 'isAuto' in options ? options.isAuto : true; // 否自动滚动加载
|
||||
var moreText = options.moreText || i18n.$t('flow.loadMore'); // 手动加载时,加载更多按钮文案
|
||||
var end = options.end || i18n.$t('flow.noMore'); // “末页”显示文案
|
||||
var direction = options.direction || 'bottom';
|
||||
var isTop = direction === 'top';
|
||||
CONST: {
|
||||
ELEM_LOAD: '<i class="layui-anim layui-anim-rotate layui-anim-loop layui-icon layui-icon-loading-1"></i>',
|
||||
ELEM_MORE: 'layui-flow-more',
|
||||
FLOW_SCROLL_EVENTS: 'scroll.lay_flow_scroll',
|
||||
LAZYIMG_SCROLL_EVENTS: 'scroll.lay_flow_lazyimg_scroll',
|
||||
},
|
||||
|
||||
// 重复执行时清理旧的事件绑定
|
||||
that._cleanup(elem, scrollElem);
|
||||
// 渲染
|
||||
render: function() {
|
||||
var that = this;
|
||||
var options = that.config;
|
||||
|
||||
//滚动条所在元素是否为document
|
||||
var notDocument = options.scrollElem && options.scrollElem !== document;
|
||||
var page = 0;
|
||||
var locked;
|
||||
var finished;
|
||||
|
||||
//加载更多
|
||||
var ELEM_TEXT = '<cite>' + moreText + '</cite>'
|
||||
,more = $('<div class="layui-flow-more"><a href="javascript:;">'+ ELEM_TEXT +'</a></div>');
|
||||
var elem = options.elem;
|
||||
if (!elem[0]) return;
|
||||
|
||||
if(!elem.find('.layui-flow-more')[0]){
|
||||
elem[isTop ? 'prepend' : 'append'](more);
|
||||
}
|
||||
var scrollElem = $(options.scrollElem || document); // 滚动条所在元素
|
||||
var threshold = 'mb' in options ? options.mb : 50; // 临界距离
|
||||
var isAuto = 'isAuto' in options ? options.isAuto : true; // 否自动滚动加载
|
||||
var moreText = options.moreText || i18n.$t('flow.loadMore'); // 手动加载时,加载更多按钮文案
|
||||
var endText = options.end || i18n.$t('flow.noMore'); // “末页”显示文案
|
||||
var direction = options.direction || 'bottom';
|
||||
var isTop = direction === 'top';
|
||||
|
||||
//加载下一个元素
|
||||
var next = function(html, over){
|
||||
var scrollHeightStart = notDocument ? scrollElem.prop('scrollHeight') : document.documentElement.scrollHeight;
|
||||
var scrollTopStart = scrollElem.scrollTop();
|
||||
html = $(html);
|
||||
more[isTop ? 'after' : 'before'](html);
|
||||
over = over == 0 ? true : null;
|
||||
over ? more.html(end) : more.find('a').html(ELEM_TEXT);
|
||||
isOver = over;
|
||||
lock = null;
|
||||
lazyimg && lazyimg();
|
||||
if(isTop){
|
||||
var scrollHeightEnd = notDocument ? scrollElem.prop('scrollHeight') : document.documentElement.scrollHeight;
|
||||
if(page === 1){
|
||||
// 首次渲染后滑动到底部
|
||||
scrollElem.scrollTop(scrollHeightEnd);
|
||||
}else if(page > 1){
|
||||
var nextElementHeight = scrollHeightEnd - scrollHeightStart;
|
||||
scrollElem.scrollTop(scrollTopStart + nextElementHeight);
|
||||
}
|
||||
}
|
||||
};
|
||||
// 滚动条所在元素是否为 document
|
||||
var notDocument = options.scrollElem && options.scrollElem !== document;
|
||||
|
||||
//触发请求
|
||||
var done = function(){
|
||||
lock = true;
|
||||
more.find('a').html(ELEM_LOAD);
|
||||
typeof options.done === 'function' && options.done(++page, next);
|
||||
};
|
||||
// 加载更多
|
||||
var ELEM_TEXT = '<cite>' + moreText + '</cite>';
|
||||
var $more = $('<div class="'+ CONST.ELEM_MORE +'"><a href="javascript:;">'+ ELEM_TEXT +'</a></div>');
|
||||
|
||||
done();
|
||||
elem.find('.'+ CONST.ELEM_MORE).remove(); // 清除旧的「加载更多」元素
|
||||
elem[isTop ? 'prepend' : 'append']($more);
|
||||
|
||||
//不自动滚动加载
|
||||
more.find('a').on('click.flow', function(){
|
||||
var othis = $(this);
|
||||
if(isOver) return;
|
||||
lock || done();
|
||||
});
|
||||
// 加载下一个元素
|
||||
var next = function(content, status) {
|
||||
var scrollHeightStart = notDocument
|
||||
? scrollElem.prop('scrollHeight')
|
||||
: document.documentElement.scrollHeight;
|
||||
var scrollTopStart = scrollElem.scrollTop();
|
||||
|
||||
//如果允许图片懒加载
|
||||
if(options.isLazyimg){
|
||||
lazyimg = that.lazyimg({
|
||||
elem: options.elem + ' img'
|
||||
,scrollElem: options.scrollElem
|
||||
,direction: options.direction
|
||||
});
|
||||
}
|
||||
$more[isTop ? 'after' : 'before'](content);
|
||||
status = status == 0 ? true : null;
|
||||
status ? $more.html(endText) : $moreBtn.html(ELEM_TEXT);
|
||||
finished = status;
|
||||
locked = null;
|
||||
|
||||
if(!isAuto) return that;
|
||||
|
||||
scrollElem.on('scroll.flow', function(){
|
||||
var othis = $(this), top = othis.scrollTop();
|
||||
|
||||
if(timer) clearTimeout(timer);
|
||||
if(isOver || !elem.width()) return; //如果已经结束,或者元素处于隐藏状态,则不执行滚动加载
|
||||
|
||||
timer = setTimeout(function(){
|
||||
//计算滚动所在容器的可视高度
|
||||
var height = notDocument ? othis.height() : $(window).height();
|
||||
|
||||
//计算滚动所在容器的实际高度
|
||||
var scrollHeight = notDocument
|
||||
? othis.prop('scrollHeight')
|
||||
: document.documentElement.scrollHeight;
|
||||
|
||||
//临界点
|
||||
if(!isTop ? scrollHeight - top - height <= threshold : top <= threshold){
|
||||
lock || done();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
return that;
|
||||
};
|
||||
|
||||
//图片懒加载
|
||||
Flow.prototype.lazyimg = function(options){
|
||||
var that = this, index = 0, haveScroll;
|
||||
options = options || {};
|
||||
|
||||
var scrollElem = $(options.scrollElem || document); //滚动条所在元素
|
||||
var elem = options.elem || 'img';
|
||||
var direction = options.direction || 'bottom';
|
||||
var isTop = direction === 'top';
|
||||
|
||||
//滚动条所在元素是否为document
|
||||
var notDocument = options.scrollElem && options.scrollElem !== document;
|
||||
|
||||
//显示图片
|
||||
var show = function(item, height){
|
||||
var start = scrollElem.scrollTop(), end = start + height;
|
||||
var elemTop = notDocument ? function(){
|
||||
return item.offset().top - scrollElem.offset().top + start;
|
||||
}() : item.offset().top;
|
||||
|
||||
/* 始终只加载在当前屏范围内的图片 */
|
||||
if((isTop ? elemTop + item.height() : elemTop) >= start && elemTop <= end){
|
||||
if(item.attr('lay-src')){
|
||||
var src = item.attr('lay-src');
|
||||
layui.img(src, function(){
|
||||
var next = that.lazyimg.elem.eq(index);
|
||||
item.attr('src', src).removeAttr('lay-src');
|
||||
|
||||
/* 当前图片加载就绪后,检测下一个图片是否在当前屏 */
|
||||
next[0] && render(next);
|
||||
index++;
|
||||
}, function(){
|
||||
var next = that.lazyimg.elem.eq(index);
|
||||
item.removeAttr('lay-src');
|
||||
// 如果允许图片懒加载
|
||||
if (options.isLazyimg) {
|
||||
component.lazyimg({
|
||||
elem: options.elem.find('img[lay-src]'),
|
||||
scrollElem: options.scrollElem,
|
||||
direction: options.direction,
|
||||
id: options.id
|
||||
});
|
||||
}
|
||||
}
|
||||
}, render = function(othis, scroll){
|
||||
|
||||
//计算滚动所在容器的可视高度
|
||||
var height = notDocument ? (scroll||scrollElem).height() : $(window).height();
|
||||
var start = scrollElem.scrollTop(), end = start + height;
|
||||
if (isTop) {
|
||||
var scrollHeightEnd = notDocument ? scrollElem.prop('scrollHeight') : document.documentElement.scrollHeight;
|
||||
if (page === 1) {
|
||||
// 首次渲染后滑动到底部
|
||||
scrollElem.scrollTop(scrollHeightEnd);
|
||||
} else if(page > 1) {
|
||||
var nextElementHeight = scrollHeightEnd - scrollHeightStart;
|
||||
scrollElem.scrollTop(scrollTopStart + nextElementHeight);
|
||||
}
|
||||
}
|
||||
};
|
||||
var $moreBtn = $more.find('a');
|
||||
|
||||
that.lazyimg.elem = $(elem);
|
||||
// 触发请求
|
||||
var done = (function fn() {
|
||||
locked = true;
|
||||
$moreBtn.html(CONST.ELEM_LOAD);
|
||||
typeof options.done === 'function' && options.done(++page, next);
|
||||
return fn;
|
||||
})();
|
||||
|
||||
if(othis){
|
||||
show(othis, height);
|
||||
} else {
|
||||
//计算未加载过的图片
|
||||
for(var i = 0; i < that.lazyimg.elem.length; i++){
|
||||
var item = that.lazyimg.elem.eq(i), elemTop = notDocument ? function(){
|
||||
// 不自动滚动加载
|
||||
$moreBtn.on('click', function() {
|
||||
if (finished) return;
|
||||
locked || done();
|
||||
});
|
||||
|
||||
if (!isAuto) return that;
|
||||
|
||||
// 滚动条滚动事件
|
||||
var timer;
|
||||
var FLOW_SCROLL_EVENTS = CONST.FLOW_SCROLL_EVENTS + '_' + options.id;
|
||||
scrollElem.off(FLOW_SCROLL_EVENTS).on(FLOW_SCROLL_EVENTS, function() {
|
||||
var othis = $(this), top = othis.scrollTop();
|
||||
|
||||
if (timer) clearTimeout(timer);
|
||||
|
||||
// 如果已经结束,或者元素处于隐藏状态,则不执行滚动加载
|
||||
if (finished || !elem.width()) return;
|
||||
|
||||
timer = setTimeout(function() {
|
||||
// 计算滚动所在容器的可视高度
|
||||
var height = notDocument ? othis.height() : $(window).height();
|
||||
|
||||
// 计算滚动所在容器的实际高度
|
||||
var scrollHeight = notDocument
|
||||
? othis.prop('scrollHeight')
|
||||
: document.documentElement.scrollHeight;
|
||||
|
||||
// 临界点
|
||||
if(!isTop ? scrollHeight - top - height <= threshold : top <= threshold){
|
||||
locked || done();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var CONST = component.CONST;
|
||||
|
||||
/**
|
||||
* 扩展组件原型方法
|
||||
*/
|
||||
|
||||
// 保留原接口,确保向下兼容
|
||||
$.extend(component, {
|
||||
load: function(options) {
|
||||
return component.render(options);
|
||||
},
|
||||
|
||||
// 图片懒加载
|
||||
lazyimg: function(options) {
|
||||
options = options || {};
|
||||
|
||||
var scrollElem = $(options.scrollElem || document); // 滚动条所在元素
|
||||
var elem = options.elem || 'img';
|
||||
var direction = options.direction || 'bottom';
|
||||
var isTop = direction === 'top';
|
||||
var index = 0;
|
||||
|
||||
// 滚动条所在元素是否为 document
|
||||
var notDocument = options.scrollElem && options.scrollElem !== document;
|
||||
|
||||
// 显示图片
|
||||
var render = (function fn(othis) {
|
||||
var $elem = $(elem);
|
||||
|
||||
// 计算滚动所在容器的可视高度
|
||||
var height = notDocument ? scrollElem.height() : $(window).height();
|
||||
var start = scrollElem.scrollTop();
|
||||
var end = start + height;
|
||||
|
||||
var show = function(item) {
|
||||
var elemTop = notDocument ? function(){
|
||||
return item.offset().top - scrollElem.offset().top + start;
|
||||
}() : item.offset().top;
|
||||
|
||||
show(item, height);
|
||||
index = i;
|
||||
/* 始终只加载在当前屏范围内的图片 */
|
||||
if ((isTop ? elemTop + item.height() : elemTop) >= start && elemTop <= end) {
|
||||
if(item.attr('lay-src')){
|
||||
var src = item.attr('lay-src');
|
||||
layui.img(src, function() {
|
||||
var next = $elem.eq(index);
|
||||
item.attr('src', src).removeAttr('lay-src');
|
||||
|
||||
//如果图片的top坐标,超出了当前屏,则终止后续图片的遍历
|
||||
if(elemTop > end) break;
|
||||
/* 当前图片加载就绪后,检测下一个图片是否在当前屏 */
|
||||
next[0] && render(next);
|
||||
index++;
|
||||
}, function() {
|
||||
item.removeAttr('lay-src');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (othis) {
|
||||
show(othis);
|
||||
} else {
|
||||
// 计算未加载过的图片
|
||||
for (var i = 0; i < $elem.length; i++) {
|
||||
var item = $elem.eq(i), elemTop = notDocument ? function(){
|
||||
return item.offset().top - scrollElem.offset().top + start;
|
||||
}() : item.offset().top;
|
||||
|
||||
show(item);
|
||||
index = i;
|
||||
|
||||
// 如果图片的 top 坐标,超出了当前屏,则终止后续图片的遍历
|
||||
if (elemTop > end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render();
|
||||
return fn;
|
||||
})();
|
||||
|
||||
if(!haveScroll){
|
||||
// 滚动事件
|
||||
var timer;
|
||||
scrollElem.on('scroll.lazyimg' , function(){
|
||||
var othis = $(this);
|
||||
if(timer) clearTimeout(timer)
|
||||
var id = options.id || '';
|
||||
var LAZYIMG_SCROLL_EVENTS = CONST.LAZYIMG_SCROLL_EVENTS + '_' + id;
|
||||
scrollElem.off(LAZYIMG_SCROLL_EVENTS).on(LAZYIMG_SCROLL_EVENTS, function() {
|
||||
if (timer) clearTimeout(timer)
|
||||
timer = setTimeout(function(){
|
||||
render(null, othis);
|
||||
render();
|
||||
}, 50);
|
||||
});
|
||||
haveScroll = true;
|
||||
|
||||
return render;
|
||||
}
|
||||
return render;
|
||||
};
|
||||
});
|
||||
|
||||
// 重复执行时清理旧的事件绑定,私有方法
|
||||
Flow.prototype._cleanup = function(elem, scrollElem){
|
||||
scrollElem.off('scroll.flow').off('scroll.lazyimg');
|
||||
elem.find('.layui-flow-more').find('a').off('click.flow');
|
||||
}
|
||||
|
||||
//暴露接口
|
||||
exports('flow', new Flow());
|
||||
exports(CONST.MOD_NAME, component);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user