可视化范围加载复习

 1、定义监听函数,监听onscroll事件

 2、提前占位,并且能获取每个模块的高度

 3、判断是否在可视范围内,如果在,则加载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <style type="text/css">
    body{
      height: 937px;
      margin: 0px;
    }
  </style>
</head>
<body>
  <h2 id="title">可视范围加载</h2>
  <div id="main"></div>
  <script>
    <!-- 模拟模块 定义高度-->
    class module {
      setContent(content) {
        this.content = content;
      }
      content;
      create() {
        return `<div id="content_${this.content}" style="height: ${this.height}px;border: 1px solid red;">${this.content}</div>`
      }
      height = 500;
      getHeight() {
        return this.height;
      }
    }

    window.onload = function(){
      const moduleArr = [];
      const moduleStrArr = [];
      for (let i = 0; i < 100; i++) {
        const _module = new module(i);
        _module.setContent(i);
        moduleStrArr.push(_module.create());
        moduleArr.push(_module)
      }
      const div = document.getElementById('main');
      div.innerHTML = moduleStrArr.join('');
      document.body.appendChild(div);

    };
    // 滚动
    window.onscroll = debounce(()=>{
      for (let i = 0; i < 100; i++) {
        if (isVisible(document.getElementById('content_'+i))) {
          console.log(i);
          // 下发处理
        }
      }
    }, 200);

    /**
     * 防抖  第一次不会立即执行
     * @date 2019/12/6
     */
    /**
     * @desc 函数防抖
     * @param fn 函数
     * @param timeout 延迟执行毫秒数
     * @param immediate true 表立即执行,false 表非立即执行
     */
    function debounce(fn, timeout, immediate) {
      let _timeout;
      return function () {
        let context = this;
        let args = arguments;

        if (_timeout) clearTimeout(_timeout);
        if (immediate) {
          let callNow = !_timeout;
          _timeout = setTimeout(() => {
            _timeout = null;
          }, timeout);
          if (callNow) fn.apply(context, args)
        } else {
          _timeout = setTimeout(function(){
            fn.apply(context, args)
          }, timeout);
        }
      }
    }

    /**
     * @desc 函数节流
     * @param fn 函数
     * @param timeout 延迟执行毫秒数
     * @param type 1 表时间戳版,2 表定时器版
     */
    function throttle(fn, timeout ,type) {
      let previous = 0;
      let _timeout;

      return function() {
        let context = this;
        let args = arguments;
        if(type===1){
          let now = Date.now();

          if (now - previous > timeout) {
            fn.apply(context, args);
            previous = now;
          }
        }else if(type===2){
          if (!_timeout) {
            _timeout = setTimeout(() => {
              _timeout = null;
              fn.apply(context, args)
            }, timeout)
          }
        }
      }
    }

    /**
     * @函数名称:
     * @作用:判断是否在可视范围内 目前只处理高度
     * @date 2019/12/6
     */
    function isVisible(el) {
      const _el = el ? getElementPosition(el) : '';
      if (_el) {
        const windowSize = getWindowSize();
        // clientHeight 元素的可视高度,内部滚动,border margin不会计算 padding会计算
        // _el.top offsetTop  元素距离上方或者上层控件的位置
        // pageYOffset 元素在窗口左上角水平和垂直方向滚动的像素。
        // availHeight 窗口的可视高度
        // _el.top + el.clientHeight > window.pageYOffset 元素的上偏移值+元素的内部高度>浏览器窗口竖直方向滑动值  上面滚入
        // window.pageYOffset + windowSize.availHeight> _el.top 浏览器窗口竖直方向滑动值+浏览器视口高度>元素的上偏移值 下面滚出
        return _el.top + el.clientHeight > window.pageYOffset && window.pageYOffset + windowSize.availHeight > _el.top;
      }
      return false;
    }

    /**
     * @函数名称:
     * @param
     * @作用:获取元素的左边和上边的位置
     * @date 2019/12/6
     */
    function getElementPosition(obj) {
      var top = 0;
      var left = 0;

      while(obj){
        top += obj.offsetTop;
        left += obj.offsetLeft;

        obj = obj.offsetParent;
      }
      return {top,left};
    }


    /**
     *
     * @returns {
     * {width: *, height: *, 内容宽高
     * availWidth: *, availHeight: 可视宽高
     * *, screenHeight: Number, screenWidth: Number 分辨率宽高
     * }}
     */
    function getWindowSize() {
      let xScroll;
      let yScroll;
      let pageWidth;
      let pageHeight;
      if (window.innerHeight && window['scrollMaxY']) {
        xScroll = window.innerWidth + window['scrollMaxX'];
        yScroll = window.innerHeight + window['scrollMaxY'];
      } else {
        if (document.body.scrollHeight > document.body.offsetHeight) {
          // all but Explorer Mac
          xScroll = document.body.scrollWidth;
          yScroll = document.body.scrollHeight;
        } else {
          // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
          xScroll = document.body.offsetWidth;
          yScroll = document.body.offsetHeight;
        }
      }
      let windowWidth, windowHeight;
      if (self.innerHeight) {
        // all except Explorer
        if (document.documentElement.clientWidth) {
          windowWidth = document.documentElement.clientWidth;
        } else {
          windowWidth = self.innerWidth;
        }
        windowHeight = self.innerHeight;
      } else {
        if (document.documentElement && document.documentElement.clientHeight) {
          // Explorer 6 Strict Mode
          windowWidth = document.documentElement.clientWidth;
          windowHeight = document.documentElement.clientHeight;
        } else {
          if (document.body) {
            // other Explorers
            windowWidth = document.body.clientWidth;
            windowHeight = document.body.clientHeight;
          }
        }
      }
      // for small pages with total height less then height of the viewport
      if (yScroll < windowHeight) {
        pageHeight = windowHeight;
      } else {
        pageHeight = yScroll;
      }
      // for small pages with total width less then width of the viewport
      if (xScroll < windowWidth) {
        pageWidth = xScroll;
      } else {
        pageWidth = windowWidth;
      }
      return {
        width: pageWidth,
        height: pageHeight,
        availWidth: windowWidth,
        availHeight: windowHeight,
        screenHeight: window.screen.height,
        screenWidth: window.screen.width,
      };
    }
  </script>
</body>
</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值