Skip to content

infinite-scroll.js

js
const observerOptions = {
  threshold: [0, .25, .5, .75, 1]
}
const DETECT_RATIO = .5
const mountInfiniteScroll = (options) => {
  const {
    detector,
    detectListener,
    detectRatio = DETECT_RATIO,
  } = options
  const observer = (elem) => {
    const [{intersectionRatio, isIntersecting}] = elem
    if (intersectionRatio >= detectRatio && isIntersecting) {
      detectListener()
    }
  }
  const intersectionObserver = new IntersectionObserver(observer, observerOptions)
  intersectionObserver.observe(detector);
}

index.html

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="wrapper">
  <div class="detector"></div>
</div>
<script src="infinite-scroll.js"></script>
<script src="script.js"></script>
</body>
</html>

script.js

js
const STEP = 10
let currentNum = 0

const assign = (obj, ...objs) => Object.assign(obj, ...objs)
const findElem = selector => document.querySelector(selector)

const addElems = () => {
  const wrapper = findElem('.wrapper')
  const detector = findElem('.detector')
  const frag = document.createDocumentFragment()
  const liTag = assign(document.createElement('div'), {
    className: 'box'
  })

  Array
    .from({length: STEP})
    .map((v, i) => {
      const textContent = currentNum + i + 1
      return assign(liTag.cloneNode(), {textContent})
    })
    .forEach(elem => {
      frag.appendChild(elem)
    })
  wrapper.insertBefore(frag, detector)
  currentNum += STEP
}

window.onload = () => {
  addElems()
  mountInfiniteScroll({
    detector: findElem('.detector'),
    detectListener: addElems,
    detectRatio: .5,
  })
}

style.css

css
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%
}

.wrapper {
  position: relative;
  width: 300px;
  height: 600px;
  border: solid 3px #999;
  overflow-y: auto
}

.box {
  width: 100%;
  height: 100px;
  float: left;
  box-sizing: border-box;
  padding: 10px;
  border: solid 1px #999
}

.detector {
  width: 100%;
  height: 50px;
  float: left;
  background-color: #f00
}