Fork Me On Github
zodream 技术 2017-10-28

先上代码

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

点击查看全文
0 310 0