-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
原生JS实现最简单的图片懒加载 #1
Labels
Comments
Open
@leixus 😁 |
被你发现了###
|
有完整得代码吗? |
@axuebin 大佬,用了介绍的第三种方式实现了图片的懒加载,但是发现当页面滚动过快的时候,el.src = source这个赋值有很多元素时候没有执行,导致了img虽然在可视区域了,但是src属性还是不存在,这个怎么破呢? |
@phonet 试试用下函数节流,不要让滚动快速执行事件, |
demo打不开也,楼主 |
@haoyi2015 谢谢提醒,可以了 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
试一下自己撸一个图片懒加载...
Demo地址:http://axuebin.com/lazyload
照片都是自己拍的哦~
懒加载
什么是懒加载
懒加载其实就是延迟加载,是一种对网页性能优化的方式,比如当访问一个页面的时候,优先显示可视区域的图片而不一次性加载所有图片,当需要显示的时候再发送图片请求,避免打开网页时加载过多资源。
什么时候用懒加载
当页面中需要一次性载入很多图片的时候,往往都是需要用懒加载的。
懒加载原理
我们都知道HTML中的
<img>
标签是代表文档中的一个图像。。说了个废话。。<img>
标签有一个属性是src
,用来表示图像的URL,当这个属性的值不为空时,浏览器就会根据这个值发送请求。如果没有src
属性,就不会发送请求。嗯?貌似这点可以利用一下?
我先不设置
src
,需要的时候再设置?nice,就是这样。
我们先不给
<img>
设置src
,把图片真正的URL放在另一个属性data-src
中,在需要的时候也就是图片进入可视区域的之前,将URL取出放到src
中。实现
HTML结构
仔细观察一下,
<img>
标签此时是没有src
属性的,只有alt
和data-src
属性。如何判断元素是否在可视区域
方法一
网上看到好多这种方法,稍微记录一下。
document.documentElement.clientHeight
获取屏幕可视窗口高度element.offsetTop
获取元素相对于文档顶部的距离document.documentElement.scrollTop
获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离然后判断②-③<①是否成立,如果成立,元素就在可视区域内。
方法二 getBoundingClientRect
通过
getBoundingClientRect()
方法来获取元素的大小以及位置,MDN上是这样描述的:这个方法返回一个名为
ClientRect
的DOMRect
对象,包含了top
、right
、botton
、left
、width
、height
这些值。MDN上有这样一张图:
可以看出返回的元素位置是相对于左上角而言的,而不是边距。
我们思考一下,什么情况下图片进入可视区域。
假设
const bound = el.getBoundingClientRect();
来表示图片到可视区域顶部距离;并设
const clientHeight = window.innerHeight;
来表示可视区域的高度。随着滚动条的向下滚动,
bound.top
会越来越小,也就是图片到可视区域顶部的距离越来越小,当bound.top===clientHeight
时,图片的上沿应该是位于可视区域下沿的位置的临界点,再滚动一点点,图片就会进入可视区域。也就是说,在
bound.top<=clientHeight
时,图片是在可视区域内的。我们这样判断:
这里有个+100是为了提前加载。
加载图片
页面打开时需要对所有图片进行检查,是否在可视区域内,如果是就加载。
这里应该是有一个优化的地方,设一个标识符标识已经加载图片的index,当滚动条滚动时就不需要遍历所有的图片,只需要遍历未加载的图片即可。
函数节流
在类似于滚动条滚动等频繁的DOM操作时,总会提到“函数节流、函数去抖”。
所谓的函数节流,也就是让一个函数不要执行的太频繁,减少一些过快的调用来节流。
基本步骤:
这里的
mustRun
就是调用函数的时间间隔,无论多么频繁的调用fn
,只有remaining>=mustRun
时fn
才能被执行。实验
页面打开时
可以看出此时仅仅是加载了img1和img2,其它的img都没发送请求,看看此时的浏览器
第一张图片是完整的呈现了,第二张图片刚进入可视区域,后面的就看不到了~
页面滚动时
当我向下滚动,此时浏览器是这样
此时第二张图片完全显示了,而第三张图片显示了一点点,这时候我们看看请求情况
img3的请求发出来,而后面的请求还是没发出~
全部载入时
当滚动条滚到最底下时,全部请求都应该是发出的,如图
完整demo
在这哦:http://axuebin.com/lazyload
更新
方法三 IntersectionObserver
经大佬提醒,发现了这个方法
先附上链接:
jjc大大:justjavac/the-front-end-knowledge-you-may-not-know#10
阮一峰大大:http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html
API Sketch for Intersection Observers:https://github.com/WICG/IntersectionObserver
IntersectionObserver
可以自动观察元素是否在视口内。callback的参数是一个数组,每个数组都是一个
IntersectionObserverEntry
对象,包括以下属性:我们需要用到
intersectionRatio
来判断是否在可视区域内,当intersectionRatio > 0 && intersectionRatio <= 1
即在可视区域内。代码
The text was updated successfully, but these errors were encountered: