jquery插件系列之延迟加载
先上代码
enum LazyMode { once, // 执行一次模式 every //永久执行模式 } class LazyItem { constructor( public element: JQuery, public callback: Function, public mode: LazyMode = LazyMode.once, public diff: number = 0 ) { } private _lastHeight: number; // 上次执行的高度 /** * 重新刷新 */ public refresh() { this._lastHeight = undefined; } /** * 判断能否执行 * @param height * @param bottom */ public canRun(height: number, bottom: number): boolean { if (this.mode == LazyMode.once && this._lastHeight) { return false } let top = this.element.offset().top; return top + this.diff >= height && top < bottom; } public run(height: number, bottom: number): boolean { if (this.mode == LazyMode.once && this._lastHeight) { return false; } let top = this.element.offset().top; if (top + this.diff < height || top >= bottom) { return false; } this.callback.call(this, this.element); this._lastHeight = height + this.diff; return true; } } class Lazy { constructor( public element: JQuery, options?: LazyOptions ) { this.options = $.extend({}, new LazyDefaultOptions(), options); let $window = $(window); let instance = this; this._init(); $window.scroll(function() { instance.scrollInvote(); }); // 首次执行 this.scrollInvote(); } public options: LazyOptions; private _data: Array<LazyItem>; /** * 页面滚动触发更新 */ public scrollInvote() { let $window = $(window); let height = $window.scrollTop(); let bottom = $window.height() + height; this.run(height, bottom); } public run(height: number, bottom: number) { if (!this._data) { return; } for(let i = this._data.length - 1; i >= 0; i --) { let item = this._data[i]; if (item.run(height, bottom) && item.mode == LazyMode.once) { this._data.splice(i, 1); } } } // 暂时只做一次 private _init() { if (typeof this.options.callback != 'function') { this.options.callback = Lazy.getMethod(this.options.callback); } this._data = []; let instance = this; this.element.each(function(i, ele) { let item = new LazyItem($(ele), instance.options.callback, instance.options.mode, instance.options.diff); instance._data.push(item); }); } /** * 全局方法集合 */ public static methods: {[name: string]: Function} = {}; /** * 添加方法 * @param name * @param callback */ public static addMethod(name: string, callback: Function) { this.methods[name] = callback; } /** * 获取方法 * @param name */ public static getMethod(name: string): Function { return this.methods[name]; } } /** * 加载图片,如需加载动画控制请自定义 */ Lazy.addMethod('img', function(imgEle: JQuery) { var img = imgEle.attr('data-original'); $("<img />") .bind("load", function() { imgEle.attr('src', img); }).attr('src', img); }); /** * 加载模板,需要引用 template 函数 */ Lazy.addMethod('tpl', function(tplEle: JQuery) { var url = tplEle.attr('data-url'); var templateId = tplEle.attr('data-tpl'); $.getJSON(url, function(data) { if (data.code != 0) { return; } if (typeof data.data != 'string') { data.data = template(templateId, data.data); } tplEle.html(data.data); }); }); interface LazyOptions { [setting: string]: any, data?: {[tag: string]: string | Object} | Array<Object> | Array<Lazy>, // 忘记了最初要做什么了,等想起来再加上对应功能 tag?: string| JQuery, callback?: string | Function, // 回调 mode?: LazyMode, //执行模式 diff?: number, //距离可视化区域的距离 } class LazyDefaultOptions implements LazyOptions { mode: LazyMode = LazyMode.once; diff: number = 0 } ;(function($: any) { $.fn.lazyload = function(options ?: LazyOptions) { return new Lazy(this, options); }; })(jQuery);
本插件使用 typescript 编写, js 请查看 GITHUB
本插件内置两个方法:
1.简单的图片加载。可以参考增加加载动画 给 img 的 src 设置一张 加载动态图片
<img class="lazy" data-original="1.jpg"/>
$("img.lazy").lazyload({ callback: function($this) { var img = $this.attr('data-original'); if (!img) { return; } $("<img />").bind("load", function() { $this.attr('src', img); }).attr('src', img); } });
2.局部加载。依赖 template 函数(参考 art-template)
<div class="templateLazy lazy-loading" data-url="1" data-tpl="temp_tpl"> </div>
主要有两个参数 :
data-url 请求网址
data-tpl 模板元素id
(lazy-loading 为加载动画)
<script id="temp_tpl" type="text/template"> <div>{{ id }}</div> </script>
$(".templateLazy").lazyload({ callback: function($this) { var url = $this.attr('data-url'); var templateId = $this.attr('data-tpl'); $.getJSON(url, function(data) { if (data.code != 0) { return; } if (typeof data.data != 'string') { data.data = template(templateId, data.data); } $this.removeClass('lazy-loading'); $this.html(data.data); }); } });
请注意,本插件依赖 jquery