jerryni / blog

:dog: :dog: :dog:
https://github.com/jerryni/blog/issues
11 stars 4 forks source link

jquery.lazyload 插件 源码分析 #11

Open jerryni opened 8 years ago

jerryni commented 8 years ago

jquery.lazyload.js的源码地址: https://github.com/tuupola/jquery_lazyload/blob/master/jquery.lazyload.js

基本思路

首先给img标签设置自定义属性, 如data-src=图片真实URI, src为placeholder图片(如1x1px的图片); 在图片进入可视区域的时候, 将src设置成图片真实URI;

如何判断元素在可视区域思路分析

也就是元素在容器的范围内, 情况有2种:

完全包含: img2

边缘包含: img2

反向思考可以想到, 如果有一个边缘不在容器里的话, 那么元素就不在可视区域了

看下图:

img1

说明:

因为4个边缘计算方式是同理的, 所以这边就以左边为例子

得出结论:

cl >= (sl + sw)的时候, 蓝色矩形是会在红色矩形左侧的;

关键代码分析

判断元素在容器左侧

  • 容器默认是window
  • 设置属性里加入了threshold(阀值)
$.leftofbegin = function(element, settings) {
    var fold;

    if (settings.container === undefined || settings.container === window) {
        fold = $window.scrollLeft();
    } else {
        fold = $(settings.container).offset().left;
    }

    return fold >= $(element).offset().left + settings.threshold + $(element).width();
};

判断元素在可视区域内

$.inviewport = function(element, settings) {
    return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) &&
        !$.belowthefold(element, settings) && !$.abovethetop(element, settings);
};

自定义事件的使用

源码中的相关片段:

// one事件是只触发一次的事件方法
$self.one("appear", function() { 
    //这里是加载图片的一些代码............
});

// 进入可视区域后触发事件
$self.trigger("appear");

自定义$.expr[":"]的基本使用

:表达式也是一种选择器过滤方法;

内置的一些, 如:

源码中的相关片段, 添加了自定义过滤方法:

/*Use as $("img:below-the-fold").something()*/
$.extend($.expr[":"], {
    "below-the-fold": function(a) {
        return $.belowthefold(a, { threshold: 0 }); }
);

自己简单写个demo测试下$.expr[':']

功能是, 选中纯数字输入的input框, 代码如下:

html:

<input type="text" value="123">
<input type="text" value="123a">

script:

$.extend($.expr[':'], {
    'number': function (el) {
        return !isNaN(el.value);
    }
});

$('input:text:number'); // => <input type="text" value="123">
jerryni commented 8 years ago

想起来一个类似的优化方案, 记录下

在移动端, 如果列表项太多, 这样dom太多, 会导致手机性能下降

看了下手淘列表页的解决方案如下:

以5页为一个单位, 如, 显示第10条的时候, 去掉前5条的dom,并设置原有高度,同时加上recycle类, 下次划上来的时候,可根据recycle类将数据再加载出来

taobao