✍️ Tangxt | ⏳ 2020-07-05 | 🏷️ DOM 操作 |
关于DOM操作,有好多好玩的属性和方法,但IE就是不支持,所以遇到要求你兼容IE的公司,那就走吧!
IE趣事:
连IE都有勇气问你是否要将它设成预设浏览器,你他妈却跟我说你没勇气跟喜欢的人表白
but,IE说「我爹是微软」
也叫图片的懒加载
像你打开淘宝这样的网站,里边都会有很多图片,而这些图片都设有延迟加载,当然,如果你的网速贼快,可能没有明显的看到效果
一个网页如果图片过多,一次性加载完的话,那么页面的渲染就贼鸡儿慢了,即你会一直看到地专栏旁边的按钮在「转圈圈」
图片懒加载的效果是这样的(个人猜测):
一些使用场景:
图片延迟加载(也叫图片懒加载):
没想到第一屏也得延迟加载 -> 淘宝也是这样做的(有加载的图标),之后其它屏,就用骨架屏替代之了……即咩有图标了……
不用具体图片,用盒子替代之……
<div class="imgBox" id="box">
<img src="" alt="" trueImg="images/1013-1200.jpg" />
</div>
* {
margin: 0;
padding: 0;
}
img {
/* 样式兼容性处理,一些浏览器对图片有默认的border */
border: none;
}
/* 隐藏图片 -> 父容器撑不起来了 */
img[src=""] {
display: none;
}
.imgBox {
box-sizing: border-box;
/* 让盒子杵在第二屏 */
margin: 800px auto;
/* 让盒子撑起来 -> 大小与图片尺寸对应 */
width: 1013px;
height: 1200px;
/* 给个灰色显示地表示在占位 -> 用于放图片 */
background: #ccc;
}
.imgBox img {
/* 图片出现了还得给个样式 */
width: 100%;
height: 100%;
/* 图片一开始默认就是隐藏的,相当于咩有写img元素一样 */
/* 这行会引起重绘吗?图片算是imgBox的内容吗?渲染树发生变化是否会引发重排呢? */
display: none;
}
/*
* offset:获取当前元素距离BODY的左/上偏移(不论其父参照物是谁)
* @params
* curEle:current element当前要操作的元素
* @return
* [object]包含上/左偏移的信息 => {top:xxx,left:xxx}
* by zhufengpeixun on 2019/08/14
*/
function offset(curEle) {
let par = curEle.offsetParent,
l = curEle.offsetLeft,
t = curEle.offsetTop;
while (par && par.tagName !== "BODY") {
if (!/MSIE 8\.0/.test(navigator.userAgent)) {
l += par.clientLeft;
t += par.clientTop;
}
l += par.offsetLeft;
t += par.offsetTop;
par = par.offsetParent;
}
return {
top: t,
left: l,
};
}
/*
* 图片完全显示出来的条件
* A:盒子底边距离BODY(页面最顶端)的距离:盒子的高度+盒子距BODY的上偏移
* B:浏览器底边距离BODY的距离:一屏幕的高度 + 卷去的高度
* A<=B:盒子就完全出现在用户的视野中
* 让图片显示
* 获取图片TRUE-IMG属性的值,赋值给SRC属性,当图片能正常加载出来后,让图片显示即可
*/
let imgBox = document.querySelector(".imgBox"),
_img = imgBox.querySelector("img");
//=>显示图片
//curImg:要显示的图片
function lazyImg(curImg) {
//给SRC赋值真实的图片地址
let trueImg = curImg.getAttribute("trueImg");
curImg.src = trueImg;
//校验图片是否能够正常加载出来:IMG.ONLOAD事件用来监听图片是否能加载
curImg.onload = function() {
curImg.style.display = "block";
};
//=>设置自定义属性:isLoad存储当前图片已经加载过了
curImg.isLoad = true;
}
function whenLazyImg() {
//=>已经加载过就不要在重复加载了
if (_img.isLoad) return;
let HTML = document.documentElement,
B = HTML.clientHeight + HTML.scrollTop,
A = imgBox.offsetHeight + offset(imgBox).top; //=>当前案例中,获取距离BODY的上偏移完全可以imgBox.offsetTop,因为父参照物就是BODY
if (A <= B) {
//=>符合图片显示的条件了
lazyImg(_img);
}
}
//=>监听页面滚动事件(不论基于什么方式,只要页面滚动了,则触发事件)
window.onscroll = throttle(whenLazyImg);
滚动到盒子完全显示的时候再去加载图片,而不是出来一个小边边就去加载显示,如:
所以,我们需要判断图片刚好或者超出完全出现在viewport时,需要 do something…… -> JS 出马
判断思路:
图片刚好完全出现在viewport: 卷去的高度+一屏的高度
用程序模拟我们的肉眼…… -> 一切皆数据
注意:如果出现水平滚动条,计算规则就不准确了,如,一屏的高度得削掉 17px
,盒子刚好完全出现又得多滚动 17px
PC端页面一般不会出现横滚动条 -> 代码测试后,发现并不需要更改计算规则……
17px
的误差是可以接受的!
还有, box
的父级参照物不一定是默认的 body
元素!所以还得用之前写的 offset
方法来得到 box
距离 body
的上偏移值!
最终代码演示效果:图片延迟加载
Q:如何获取写在结构上的自定义属性?
只能通过 getAttribute([自定义属性名])
这个方法来获取!
如: curImg.getAttribute("trueImg")
Q: `querySelector()` ?
从选中的一个或多个元素里边,只获取第一个!
Q:如果给的图片地址错了?
需要监听一下图片的 onload
事件,只有加载成功了,才去显示图片
而且即便图片地址错了,即咩有加载成功,也是要走isLoad = true
这个逻辑,而不是说,再重新加载一下,毕竟这是图片地址错了,可不是网络错误呀!当然,如果是网络错误,那就得「重新发请求去加载」了
Q:图片懒加载成功后,还需要监听 `scroll` 吗?
为 img
DOM 对象 设置一个自定义属性,如 isLoad
,如果 isLoad
为 true
意味着图片已经被加载过了!这样一来 lazyImg
方法就执行一次了……不然,该方法会在来回的滚动中多次执行没有必要执行的 lazyImg
方法……
Q:瀑布流怎么做?
把单张图片的操作重复 N 次! -> 那就是多张了……也就是所谓的「瀑布流」
瀑布流效果:勒布朗_花瓣_采集
Q: `display:none` ?
题外话: display:none
和 visibility:hidden
的区别?
display:none
的子孙节点消失,这是由于元素从渲染树中消失造成, visibility:hidden
会子孙节点消失是由于继承性,可以设置 visibility:visible
让子孙节点显示display:none
不占据任何空间; visibility:hidden
仍占据空间display:none
会引起回流和重绘(元素位置发生变化,或者说需要重新构建渲染树), visibility:hidden
会引起重绘(元素位置没变化)display:none
的元素内容,而会读取 visibility:hidden
的元素内容这俩东西都让我们看不见,前者是真得消失了(相当于没写这个HTML元素一样),而后者就像是个隐身的透明人
➹:渲染树构建、布局及绘制 - Web - Google Developers
➹:display:none和visibility:hidden__牛客网
img
标签的src
属性为空值 -> 有个自定义属性存储着图片的真实地址,如trueImg='./xxx.jpg'
src
为空值的img
为display:none
、盒子容器的大小 -> 图片的大小、有背景颜色、所有img
一开始都是display:none
,大小都是w/h:100%
(给个默认值,图片显示了,还得给个宽高,这样浏览器就不用自己去计算了,而且如果盒子容器宽高都写大了,也会有个自适应填充)lazyImg
呗!在玩和平精英的时候,请你选一把武器:
IE的勇气:
你唯一的价值就是被我们骂:
How to tell html from html5?(如何区分 html 和 html5?)
IE过于特立独行 -> 人人喊打 -> 又菜又要装逼……
要兼容IE6/7吗? -> 不用了
兼容的边界的是IE8,再兼容下去的话,就亏本了:
这张图详细说明了主流浏览器大战的始末(数据截止2010年底)
微软将 Internet Explorer 称为「兼容性解决方案」,而不是浏览器
如果你想磨炼你的兼容性能力,那就去兼容IE吧!
鹅厂出来的程序员都讨厌QQ浏览器(比IE还讨厌),因为一个页面写出来,首先要测试的就是QQ浏览器,而QQ浏览器的兼容性也很糟糕,当然,现在2020年,应该好很多了!