zlx362211854 / daily-study

每日一个知识点总结,以issue的形式体现
10 stars 6 forks source link

89.谈谈 IntersectionObserver #142

Open nanslee opened 4 years ago

goldEli commented 4 years ago

本质就是监听一个元素,当这个这个元素在最外层可视窗口可以看到时,就触发回调。

var observer = new IntersectionObserver(changes => {
  // 当可以在视图窗口看到时,触发这个回调
  // do some staff
}, {});

// 监听元素
observer.observe(target);

// 停止监听
observer.unobserve(target);

// 断开监听
observer.disconnect();
nanslee commented 4 years ago

IntersectionObserver接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。祖先元素与视窗(viewport)被称为根(root)。

当一个IntersectionObserver对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦IntersectionObserver被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素

    let observer = new IntersectionObserver((e) => {
        let isintersecting = e[0].isIntersecting
        console.log(e[0].intersectionRatio)
        if (isintersecting) {
            console.log('我出来了');
        }else{
            console.log('我隐藏了');
        }
    }, {
        root: null
    })

    // 观察某个目标元素,一个观察者实例可以观察任意多个目标元素。
    observer.observe(document.querySelector('.scroll-down'))
zlx362211854 commented 4 years ago

IntersectionObserver可以监听指定元素是否在指定视窗内出现

使用IntersectionObserver实现一个简单的懒加载:

<!--
 * @Author: zlx
 * @Date: 2019-12-05 09:59:39
 * @LastEditors: zlx
 * @LastEditTime: 2019-12-05 10:49:36
 * @Description: 
 -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>lazy loading</title>
  <style>
    .ul {
      width: 200px;
      height: 300px;
      overflow: auto;
    }
    .li {
      width: 100%;
      height: 30px;
      line-height: 30px;
      background: aquamarine;
      border: 1px solid salmon;
      list-style: none;
      text-align: center;
      box-sizing: border-box;
    }
  </style>
</head>
<body>
  <ul class="ul" id="ul">
  </ul>
  <script>
  /**
      * @description: 获取元素最后一个子元素
      * @param {type} 
      * @return: 
      */
    function getLastElementChild(element) {
      if(element.lastElementChild) {
        return element.lastElementChild;
      }else{
        let node=element.lastChild;
        while (node&&node.nodeType!=1) {
          node=node.previousSibling;
        }
        return node;
      }
    }

    const ul = document.getElementById('ul')
    /**
     * @description: 添加一批子元素
     * @param {type} 
     * @return: 
     */
    function append() {
      for (let i = 0; i < 11; i++) {
      const li = document.createElement('li')
      li.innerText = i + 1
      li.setAttribute('class', 'li')
      ul.appendChild(li)
      }
    }
    append()

    const io = new IntersectionObserver(function(entries) {
      if (entries[0].isIntersecting) {
        io.unobserve(getLastElementChild(ul))
        append()
        io.observe(getLastElementChild(ul))
      }
    }, {
      root: ul,
      rootMargin: '0px 0px -10px'
    })
    io.observe(getLastElementChild(ul))
  </script>
</body>
</html>
roxy0724 commented 4 years ago

其实就是观察一个元素是否在视窗范围内可见。

API

const view = new intersectionObserve(callback, options)