唯品秀前端博客

IntersectionObserver是个异步方法,使用者不必过多的关注它内部具体计算过程,应用场景如:以前我们在做图片懒加载时候需要借助插件,或者手动去计算元素是否在视窗内,反正我是记不住具体怎么算,每次都是百度一遍套公式,自从发现了IntersectionObserver,一切是变得如此的简单,不单单是通过它可以进行懒加载图片,例如很多公司需要做元素进屏展示统计等等,它都将能胜任。

api基本格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var io = new IntersectionObserver(changes => {
    for (const change of changes) {
        console.log(change.time);
        // 当可视状态变化时,状态发送改变的时间戳
        // 对比时间为,实例化的时间,
        // 比如,值为1000时,表示在IntersectionObserver实例化的1秒钟之后,触发该元素的可视性变化

        console.log(change.rootBounds);
        // 根元素的矩形区域信息,即为getBoundingClientRect方法返回的值

        console.log(change.boundingClientRect);
        // 目标元素的矩形区域的信息

        console.log(change.intersectionRect);
        // 目标元素与视口(或根元素)的交叉区域的信息

        console.log(change.intersectionRatio);
        // 目标元素的可见比例,即intersectionRect占boundingClientRect的比例,
        // 完全可见时为1,完全不可见时小于等于0

        console.log(change.target);
        // 被观察的目标元素,是一个 DOM 节点对象
        // 当前可视区域正在变化的元素

    }
}, {}); //{}为可选,其中为配置参数

// 对元素target添加监听,当target元素变化时,就会触发上述的回调
io.observe(target);

// 移除一个监听,移除之后,target元素的可视区域变化,将不再触发前面的回调函数
io.unobserve(target);

// 停止所有的监听
io.disconnect();

兼容性

最好的教程莫过于一个小demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>淘宝女郎</title>
</head>
<style>
  .girls-list-wrap {
    min-height: 400px;
    width: 100%;
    margin-top: 10px;
    overflow: hidden
  }

  .girls-list-wrap .girls-list {
    width: 1155px;
    margin: 0 auto;
    list-style: none
  }

  .girls-list-wrap .girls-list .item {
    width: 230px;
    height: 288px;
    float: left;
    position: relative;
    *display: inline;
    margin: -1px 0 0 -1px
  }

  .girls-list-wrap .girls-list .item a {
    display: block;
    text-decoration: none;
    height: 100%;
    width: 100%
  }

  .girls-list-wrap .girls-list .item a:hover .item-wrap {
    width: 246px;
    height: 304px;
    border: 2px solid #282828;
   background-color: #282828;
   margin: -10px 0 0 -10px;
    z-index: 1
  }

  .girls-list-wrap .girls-list .item a:hover .info {
    color: #fff
 }

  .girls-list-wrap .girls-list .item a:hover .info .city,
  .girls-list-wrap .girls-list .item a:hover .info .name {
    color: #fff
 }

  .girls-list-wrap .girls-list .item a:hover img {
    height: 246px
  }

  .girls-list-wrap .girls-list .item img {
    width: 100%;
    height: 228px;
    -webkit-transition-property: height;
    -webkit-transition-duration: .2s;
    -webkit-transition-timing-function: ease-in-out;
    -moz-transition-property: height;
    -moz-transition-duration: .2s;
    -moz-transition-timing-function: ease-in-out;
    -ms-transition-property: height;
    -ms-transition-duration: .2s;
    -ms-transition-timing-function: ease-in-out;
    -o-transition-property: height;
    -o-transition-duration: .2s;
    -o-transition-timing-function: ease-in-out;
    transition-property: height;
    transition-duration: .2s;
    transition-timing-function: ease-in-out
  }

  .girls-list-wrap .girls-list .item .info {
    padding-left: 10px
  }

  .girls-list-wrap .girls-list .item .info .name {
    color: #666;
   margin-right: 5px
  }

  .girls-list-wrap .girls-list .item .info .city {
    color: #a9a9a9;
   font-size: 12px;
    vertical-align: top
  }

  .girls-list-wrap .girls-list .item .row2 {
    color: #a9a9a9;
   font-size: 12px;
    margin-top: 3px
  }

  .girls-list-wrap .girls-list .item .row2 .fr {
    float: right;
    margin-right: 10px
  }

  .girls-list-wrap .girls-list .item .row2 .iconfont {
    margin-right: 5px
  }

  .girls-list-wrap .girls-list .item-wrap {
    width: 228px;
    height: 288px;
    position: absolute;
    float: left;
    border: 1px solid #a0a0a0;
   background-color: #fff;
   -webkit-transition-property: width height border margin z-index;
    -webkit-transition-duration: .2s;
    -webkit-transition-timing-function: ease-in-out;
    -moz-transition-property: width height border margin z-index;
    -moz-transition-duration: .2s;
    -moz-transition-timing-function: ease-in-out;
    -ms-transition-property: width height border margin z-index;
    -ms-transition-duration: .2s;
    -ms-transition-timing-function: ease-in-out;
    -o-transition-property: width height border margin z-index;
    -o-transition-duration: .2s;
    -o-transition-timing-function: ease-in-out;
    transition-property: width height border margin z-index;
    transition-duration: .2s;
    transition-timing-function: ease-in-out
  }
</style>

<body>
  <div class="girls-list-wrap">
    <ul class="girls-list clearfix" id="J_GirlsList">
      <li class="item">
        <a href="#">
          <div class="item-wrap">
            <div class="img"><img
                data-src="https://gtd.alicdn.com/sns_logo/i6/TB1fVJJQFXXXXcyXpXXSutbFXXX.jpg_240x240xz.jpg"
                src="https://img.alicdn.com/tps/i3/T1QYOyXqRaXXaY1rfd-32-32.gif"></div>
            <div class="info">
              <span class="name">模特雪梨</span>
              <span class="city">杭州市</span>
            </div>
            <div class="info row2">

              <span>165CM&nbsp;/&nbsp;47KG</span>

              <span class="fr"><i class="iconfont">&#x1f44d;</i>201566</span>
           </div>
          </div>
        </a>
      </li>
     <!-- 为代码简洁在此省略亿万张图片 -->
    </ul>
  </div>
</body>

</html>

js部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
var lazyLoad = new IntersectionObserver(callback, {
    root: null, //用于观察的根元素,默认是浏览器的视口,也可以指定具体元素,指定元素的时候用于观察的元素必须是指定元素的子元素
    //threshold: [0, 0.5, 1], //指定了交叉比例为0,0.5,1,当观察元素img0%、50%、100%时候就会触发回调函数
    rootMargin: '0px 0px -100px'//这个参数非常有用,用来扩大或者缩小视窗的的大小,使用css的定义方法,10px 10px 30px 20px表示top、right、bottom 和 left的值
});
let imgList = document.querySelectorAll('[data-src]');
function callback(entries) {
    console.log(entries)
    entries.forEach((item) => {
        if (item.isIntersecting) {
            item.target.src = item.target.dataset.src
            lazyLoad.unobserve(item.target)
        }
    })
}

imgList.forEach((item) => {
    lazyLoad.observe(item)
})
</script>

兼容性

IE都趴下了,现在的主浏览器基本都支持,可能有的用户老版本的不支持。解决方案有两个,第一,有对应的插件IntersectionObserver polyfill,第二,其实如果只是做图片懒加载的话,那在不支持的时候直接展示也就可以了,直接循环所有图片标签,把data-src数据赋值到真正的src即可。当然,如果你用这个做无限下拉那就不能这么干。

小结

截止目前兼容性已达到90%+,我相信在实际项目中你是可以值得一试的。温馨提示:为了更好的体验下面demo图片懒加载技术效果了解它的工作过程,你应该将浏览器网速降低到至3G等模式,具体可百度。

在线一览

本站所有文章、图片、资源等如无特殊说明或标注,均为来自互联网或者站长原创,版权归原作者所有;仅作为个人学习、研究以及欣赏!如若本站内容侵犯了原著者的合法权益,可联系我们进行处理,邮箱:343049466@qq.com
赞(7) 打赏

上一篇:

下一篇:

相关推荐

1 条评论关于"认识IntersectionObserver交叉口观察者(懒加载、预加载)"

表情

最新评论

  1. 哆啦A梦
    Windows 10 Chrome 75.0.3770.100

    不错哦,get到知识点了~

  2. 暂无留言哦~~
谢谢你请我吃鸡腿*^_^*

支付宝扫一扫打赏

微信扫一扫打赏