zoukankan      html  css  js  c++  java
  • 懒加载的效果

    <!DOCTYPE html>
    <html>
    <head>
      <title>懒加载</title>
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <style>
        body{ background: #eee; }
        ul,li{padding: 0; margin: 0; list-style: none;}
        #main .list-wrap{
          overflow: hidden;
        }
        #main .list-item{
          padding: 5px 0;
          background: #fff;
          border: 1px solid #ccc;
          overflow: hidden;
        }
        #main .pic-wrap{
          float: left;
          margin: 0 10px;
          height: 100px;
          min-width: 50px;
        }
        #main .cont-wrap{
          padding: 5px;
          color: #777;
          font-size: 14px;
          line-height: 1.4;
        }      
      </style>
    </head>
    <body>
     <div id="main">
      <ul class="list-wrap">
        <li class="list-item amfe-appear">
          <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> 
    </li>
    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    <li class="list-item amfe-appear"> <img class="pic-wrap" data-src="你的图片地址" /> <div class="cont-wrap"> 这个效果有点好 </div> </li>

    </ul> </div>
    <script src="bundle.js"></script>
    <script> (function () {

    var AmfeAppear = require('amfe-appear'); //宝贝列表实例化,查找类名包含amfe-appear的元素

    var itemAppear = AmfeAppear.appear.init({ cls: 'amfe-appear', onAppear: function(){

    //元素处在可视区域内,执行懒加载

    var img = this.querySelector('img'); // 延迟执行,方便查看效果
    setTimeout(
    function() {
    img.src
    = img.getAttribute('data-src'); }, 500); }, onDisappear: function() {

    //元素处在不可视区域内,做输出
    console.log(
    this); } });

    // 触发校验 itemAppear.fire(); }) () ;
    </script>
    </body>
    </html>
    bundle.js
      1 <script>
      2   /*bundle.js*/
      3   require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
      4     'use strict';
      5 
      6     Object.defineProperty(exports, "__esModule", {
      7       value: true
      8     });
      9 
     10     var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
     11 
     12     function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
     13 
     14     var doc = document;
     15     var appearEvt = doc.createEvent("HTMLEvents"); //创建自定义显示事件  ;
     16     var disappearEvt = doc.createEvent("HTMLEvents"); //创建自定义显示事件  ;
     17 
     18     function createEvent(eventType) {
     19       appearEvt.initEvent(eventType, false, true);
     20       disappearEvt.initEvent(eventType, false, true);
     21     }
     22 
     23     /**
     24      * [throttle 节流函数]
     25      * @param  {[function]} func [执行函数]
     26      * @param  {[int]} wait [等待时长]
     27      * @return {[type]}      [description]
     28      */
     29     function throttle(func, wait) {
     30       var previous = 0,
     31       //上次执行的时间
     32               timeout = null,
     33       //setTimout任务
     34               args = void 0,
     35       //参数
     36               result = void 0; //结果
     37       var later = function later() {
     38         previous = Date.now();
     39         timeout = null; //清空计时器
     40         func(args);
     41       };
     42       return function () {
     43         var now = Date.now(),
     44                 args = arguments,
     45                 remaining = wait - (now - previous);
     46         if (remaining <= 0 || remaining >= wait) {
     47           //如果没有剩余时间,或者存在修改过系统时间导致剩余时间增大的情况,则执行
     48           clearTimeout(timeout);
     49           timeout = null;
     50           result = func(args);
     51         } else if (timeout === null) {
     52           timeout = setTimeout(later, remaining);
     53         }
     54         return result;
     55       };
     56     }
     57 
     58     /**
     59      * [getOffset 获取边距尺寸]
     60      * @param  {[type]} el   [description]
     61      * @param  {[type]} param [description]
     62      * @return {[type]}       [description]
     63      */
     64     function getOffset(el, param) {
     65       var l, r, t, b;
     66       if (!el) {
     67         return;
     68       }
     69       if (!param) {
     70         param = {
     71           x: 0,
     72           y: 0,
     73           h: null,
     74           w: null
     75         };
     76       }
     77 
     78       if (el !== window) {
     79         el = el.getBoundingClientRect();
     80         l = el.left;
     81         t = el.top;
     82         r = el.right;
     83         b = el.bottom;
     84       } else {
     85         l = 0;
     86         t = 0;
     87         r = l + el.innerWidth;
     88         b = t + el.innerHeight;
     89       }
     90       param.h = param.h || (el.height || el.innerHeight) - param.y;
     91       param.w = param.w || (el.width || el.innerWidth) - param.x;
     92       var offset = {
     93         'left': l + (el.width || el.innerWidth) - param.w - param.x,
     94         'top': t + (el.height || el.innerHeight) - param.h - param.y,
     95         'right': r - param.x,
     96         'bottom': b - param.y
     97       };
     98       return offset;
     99     }
    100 
    101 //元素位置比较
    102     function compareOffset(d1, d2) {
    103       var left = d2.right > d1.left && d2.left < d1.right;
    104       var top = d2.bottom > d1.top && d2.top < d1.bottom;
    105       return left && top;
    106     }
    107 //获取移动方向
    108     function getDirection(beforeOffset, nowOffset) {
    109       var direction = 'none';
    110       var horizental = beforeOffset.left - nowOffset.left;
    111       var vertical = beforeOffset.top - nowOffset.top;
    112       if (vertical === 0) {
    113         if (horizental !== 0) {
    114           direction = horizental > 0 ? 'left' : 'right';
    115         } else {
    116           direction = 'none';
    117         }
    118       }
    119       if (horizental === 0) {
    120         if (vertical !== 0) {
    121           direction = vertical > 0 ? 'up' : 'down';
    122         } else {
    123           direction = 'none';
    124         }
    125       }
    126       return direction;
    127     }
    128 
    129     function extend(target, el) {
    130       for (var k in el) {
    131         if (el.hasOwnProperty(k)) {
    132           target[k] = el[k];
    133         }
    134       }
    135       return target;
    136     }
    137 
    138     /**
    139      * [__bindEvent 绑定事件,包括滚动、touchmove、transform、resize等]
    140      * @return {[type]}      [description]
    141      */
    142     function __bindEvent() {
    143       var _this = this,
    144               _arguments = arguments;
    145 
    146       var handle = throttle(function () {
    147         __fire.apply(_this, _arguments);
    148       }, this.options.wait);
    149       if (this.__handle) {
    150         //避免重复绑定
    151         this.viewWrapper.removeEventListener('scroll', this.__handle);
    152         this.__handle = null;
    153       }
    154       this.__handle = handle;
    155       this.viewWrapper.addEventListener('scroll', handle, false);
    156       this.viewWrapper.addEventListener('resize', function () {
    157         __fire.apply(_this, _arguments);
    158       }, false);
    159       this.viewWrapper.addEventListener('animationEnd', function () {
    160         __fire.apply(_this, _arguments);
    161       }, false);
    162       // android4.0以下
    163       this.viewWrapper.addEventListener('webkitAnimationEnd', function () {
    164         __fire.apply(_this, _arguments);
    165       }, false);
    166       this.viewWrapper.addEventListener('transitionend', function () {
    167         __fire.apply(_this, _arguments);
    168       }, false);
    169     }
    170 
    171 //获取容器内所有的加载元素
    172     function __getElements(selector) {
    173       var _this2 = this;
    174 
    175       //获取视窗容器
    176       var viewWrapper = this.options.viewWrapper;
    177       if (typeof viewWrapper === 'string') {
    178         //如果是字符串,则选择器
    179         this.viewWrapper = doc.querySelector(viewWrapper);
    180       } else {
    181         //对象传值
    182         this.viewWrapper = viewWrapper;
    183       }
    184       var appearWatchElements = void 0;
    185       //获取容器内的所有目标元素
    186       if (this.viewWrapper === window) {
    187         appearWatchElements = doc.querySelectorAll(selector);
    188       } else {
    189         appearWatchElements = this.viewWrapper.querySelectorAll(selector);
    190       }
    191       appearWatchElements = [].slice.call(appearWatchElements, null);
    192 
    193       appearWatchElements = appearWatchElements.filter(function (ele) {
    194         // 如果已经绑定过,清除appear状态,不再加入到数组里
    195         if (ele.dataset.bind === '1') {
    196           delete ele._hasAppear;
    197           delete ele._hasDisAppear;
    198           delete ele._appear;
    199           ele.classList.remove(_this2.options.cls);
    200           return false;
    201         } else {
    202           return true;
    203         }
    204       });
    205 
    206       return appearWatchElements;
    207     }
    208 
    209     function __initBoundingRect(elements) {
    210       var _this3 = this;
    211 
    212       if (elements && elements.length > 0) {
    213         [].forEach.call(elements, function (ele) {
    214           ele._eleOffset = getOffset(ele);
    215           //移除类名
    216           ele.classList.remove(_this3.options.cls);
    217           // 标志已经绑定
    218           ele.dataset.bind = 1;
    219         });
    220       }
    221     }
    222 
    223 // 触发加载
    224     function __fire() {
    225       var viewWrapper = this.viewWrapper,
    226               elements = this.appearWatchElements,
    227               appearCallback = this.options.onAppear,
    228       //appear的执行函数
    229               isDispatch = this.options.isDispatch,
    230       // 是否分发事件
    231               disappearCallback = this.options.onDisappear,
    232       //disappear的执行函数
    233               viewWrapperOffset = getOffset(viewWrapper, {
    234                 x: this.options.x,
    235                 y: this.options.y,
    236                 h: this.options.h,
    237                 w: this.options.w
    238               }),
    239               isOnce = this.options.once; //是否只执行一次
    240       if (elements && elements.length > 0) {
    241         [].forEach.call(elements, function (ele) {
    242           //获取左右距离
    243           var eleOffset = getOffset(ele),
    244                   direction = getDirection(ele._eleOffset, eleOffset);
    245           //保存上个时段的位置信息
    246           ele._eleOffset = eleOffset;
    247           //查看是否在可视区域范围内
    248           var isInView = compareOffset(viewWrapperOffset, eleOffset),
    249                   appear = ele._appear,
    250                   _hasAppear = ele._hasAppear,
    251                   _hasDisAppear = ele._hasDisAppear;
    252           appearEvt.data = {
    253             direction: direction,
    254             eleOffset: eleOffset
    255           };
    256           disappearEvt.data = {
    257             direction: direction,
    258             eleOffset: eleOffset
    259           };
    260           if (isInView && !appear) {
    261             if (isOnce && !_hasAppear || !isOnce) {
    262               //如果只触发一次并且没有触发过或者允许触发多次
    263               //如果在可视区域内,并且是从disppear进入appear,则执行回调
    264               var appearFn = function appearFn(ev) {
    265                 appearCallback && appearCallback.call(ele, ev);
    266                 ele.removeEventListener('appear', appearFn);
    267               };
    268               ele.addEventListener('appear', appearFn);
    269               if (isDispatch) {
    270                 //触发自定义事件
    271                 ele.dispatchEvent(appearEvt);
    272               } else {
    273                 appearFn(appearEvt);
    274               }
    275               ele._hasAppear = true;
    276               ele._appear = true;
    277             }
    278           } else if (!isInView && appear) {
    279             if (isOnce && !_hasDisAppear || !isOnce) {
    280               //如果不在可视区域内,并且是从appear进入disappear,执行disappear回调
    281               var disappearFn = function disappearFn(ev) {
    282                 disappearCallback && disappearCallback.call(ele, ev);
    283                 ele.removeEventListener('disappear', disappearFn);
    284               };
    285               ele.addEventListener('disappear', disappearFn);
    286 
    287               if (isDispatch) {
    288                 //触发自定义事件
    289                 ele.dispatchEvent(disappearEvt);
    290               } else {
    291                 disappearFn(disappearEvt);
    292               }
    293               ele._hasDisAppear = true;
    294               ele._appear = false;
    295             }
    296           }
    297         });
    298       }
    299     }
    300 
    301     function __init(opts) {
    302       //扩展参数
    303       extend(this.options, opts || (opts = {}));
    304       //注册事件
    305       createEvent(this.options.eventType);
    306       //获取目标元素
    307       this.appearWatchElements = this.appearWatchElements || __getElements.call(this, "." + this.options.cls);
    308       //初始化位置信息
    309       __initBoundingRect.call(this, this.appearWatchElements);
    310       //绑定事件
    311       __bindEvent.call(this);
    312     }
    313 
    314     var Appear = function () {
    315       function Appear() {
    316         _classCallCheck(this, Appear);
    317 
    318         //默认参数
    319         this.options = {
    320           viewWrapper: window,
    321           wait: 100,
    322           x: 0,
    323           y: 0,
    324           w: null,
    325           h: null,
    326           cls: 'amfe-appear',
    327           once: false,
    328           isDispatch: true,
    329           eventType: 'appear', // 事件类型,默认出现事件为appear、消失事件为disappear,自定义事件名,消失事件自动加上前缀dis
    330           onAppear: function onAppear() {},
    331           onDisappear: function onDisappear() {}
    332         };
    333         this.viewWrapper = null;
    334         this.appearWatchElements = null;
    335         __init.apply(this, arguments);
    336       }
    337 
    338       _createClass(Appear, [{
    339         key: "bind",
    340         value: function bind(node) {
    341           var cls = this.options.cls;
    342           // 添加需要绑定的appear元素
    343           if (typeof node === 'string') {
    344             var elements = __getElements.call(this, node);
    345             [].forEach.call(elements, function (ele) {
    346               if (!ele.classList.contains(cls)) {
    347                 ele.classList.add(cls);
    348               }
    349             });
    350           } else if (node.nodeType === 1 && (this.viewWrapper === window || this.viewWrapper.contains(node))) {
    351             //如果传入的是元素并且在包含在容器中,直接添加类名
    352             if (!node.classList.contains(cls)) {
    353               //添加类名
    354               node.classList.add(cls);
    355             }
    356           } else {
    357             return this;
    358           }
    359           //新增的子元素
    360           var newElements = __getElements.call(this, "." + this.options.cls);
    361           //对缓存的子元素做增量
    362           this.appearWatchElements = this.appearWatchElements.concat(newElements);
    363           //初始化新子元素的位置信息
    364           __initBoundingRect.call(this, newElements);
    365           return this;
    366         }
    367         // 重置函数
    368 
    369       }, {
    370         key: "reset",
    371         value: function reset(opts) {
    372           __init.call(this, opts);
    373           this.appearWatchElements.forEach(function (ele) {
    374             delete ele._hasAppear;
    375             delete ele._hasDisAppear;
    376             delete ele._appear;
    377           });
    378           return this;
    379         }
    380       }, {
    381         key: "fire",
    382         value: function fire() {
    383           if (!this.appearWatchElements) {
    384             this.appearWatchElements = [];
    385           }
    386           var newElements = __getElements.call(this, "." + this.options.cls);
    387           this.appearWatchElements = this.appearWatchElements.concat(newElements);
    388           //初始化位置信息
    389           __initBoundingRect.call(this, newElements);
    390           __fire.call(this);
    391           return this;
    392         }
    393       }]);
    394 
    395       return Appear;
    396     }();
    397 
    398     var appear = {
    399       instances: [],
    400       init: function init(opts) {
    401         var instance = new Appear(opts);
    402         this.instances.push(instance);
    403         return instance;
    404       },
    405       fireAll: function fireAll() {
    406         var instances = this.instances;
    407         instances.forEach(function (instance) {
    408           instance.fire();
    409         });
    410       }
    411     };
    412 
    413     exports.default = appear;
    414 
    415   },{}],"amfe-appear":[function(require,module,exports){
    416     'use strict';
    417 
    418     /**
    419      * @module amfeAppear
    420      */
    421 
    422     /**
    423      * @requires class:Appear
    424      */
    425 
    426     Object.defineProperty(exports, "__esModule", {
    427       value: true
    428     });
    429     exports.appear = exports.version = undefined;
    430 
    431     var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
    432 
    433     var _appear = require('./appear');
    434 
    435     var _appear2 = _interopRequireDefault(_appear);
    436 
    437     function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
    438 
    439     var version = '1.0.0';
    440     /*eslint-disable no-alert, no-console */
    441 
    442     /* istanbul ignore if */
    443     if (typeof alert === 'function' && (typeof console === 'undefined' ? 'undefined' : _typeof(console)) === 'object') {
    444       console.log('bar');
    445     }
    446 
    447     /*eslint-enable no-alert, no-console */
    448 
    449     exports.
    450     /**
    451      * version
    452      * @type {string}
    453      */
    454             version = version;
    455     exports.
    456     /**
    457      * @type {Appear}
    458      */
    459             appear = _appear2.default;
    460 
    461   },{"./appear":1}]},{},[])
    462 </script>
    js源码

    效果图就不上了,就是懒加载的效果

  • 相关阅读:
    TP5框架 《防sql注入、防xss攻击》
    jsonp跨域的原理
    PHP程序发送HTTP请求代码
    encodeURI()和encodeURIComponent() 区别
    密码存储中MD5的安全问题与替代方案
    获取用户Ip地址通用方法常见安全隐患(HTTP_X_FORWARDED_FOR)
    PHP中的调试工具 --Xdebug安装与使用
    手机端页面自适应解决方案—rem布局(进阶版,附源码示例)
    thinkphp 微信授权登录 以及微信实现分享
    PHP中使用CURL之php curl详细解析和常见大坑
  • 原文地址:https://www.cnblogs.com/heyiming/p/6873979.html
Copyright © 2011-2022 走看看