JS应用题
About 5 min
JS应用题
图片预加载和懒加载
图片预加载
- 概念:将所需的资源提前请求加载到本地,这样后面在需要用到时就直接从缓存取资源。
- 作用:减少用户的等待时间,提高用户的体验
- 方法:使用js中的image对象,通过为image对象来设置scr属性,来实现图片的预加载
图片懒加载
概念:懒加载也叫延迟加载,指的是在长网页中延迟加载图片的时机,当用户需要访问时,再去加载。
作用:
- 提高网站的首屏加载速度,提升用户的体验
- 减少请求数或延迟请求数,减少服务器的压力
适用场景:图片很多,页面很长的场景
懒加载图示:
- 图片滚动到可视区域时,浏览器才真正请求图片资源
实现原理:
- 一张图片就是一个
<img>
标签,浏览器是否发起请求图片是根据<img>
的 src 属性,所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给<img>
的 src 赋值,这样浏览器就不会发送请求了; - 将页面上的图片的 src 属性设置为空字符串,将图片的真实路径保存在一个自定义属性中
- 当页面滚动的时候,进行判断,如果图片进入页面可视区域内,则从自定义属性中取出真实路径赋值给图片的 src 属性,此时浏览器才会真正请求加载图片资源。
- 一张图片就是一个
实现步骤:
- 初始图片效果
- 方式1:加载loading图片
- 方式2:用 CSS 制造模糊效果
- 按需加载:判断哪些图片要加载【重点】。
- 方式1:Intersection_Observer:应用会新建一个它的实例。当一个或多个监听对象跟 Observer 发生交互时(即图片出现在视口中时),作为参数传递的函数可以用来处理一些回调事务(例如图片加载)。我们可以迭代每一个对象,并对它们进行相应的处理:当图片可见时,我们开始加载真正的图片并且停止监听这张图片,因为在图片加载完成之后,我们已经没必要再知道它的状态了。
- 方式2:使用 JS 监听并计算
- 隐形加载图片
- 替换真图片
- 初始图片效果
判断图片是否进入可视区域:
方式2:使用 JS 监听并计算。
让在浏览器可视区域的图片显示,可视区域外的不显示,所以当图片距离顶部的距离top-height等于可视区域h和滚动区域高度s之和时说明图片马上就要进入可视区了,就是说当
top-height<=s+h
时,图片在可视区使用 API:
- 页可见区域宽:
document.body.clientWidth
; - 网页可见区域高:
document.body.clientHeight
; - 网页可见区域宽:
document.body.offsetWidth (包括边线的宽)
; - 网页可见区域高:
document.body.offsetHeight (包括边线的宽)
; - 网页正文全文宽:
document.body.scrollWidth
; - 网页正文全文高:
document.body.scrollHeight
; - 网页被卷去的高:
document.body.scrollTop
; - 网页被卷去的左:
document.body.scrollLeft
; - 网页正文部分上:
window.screenTop
; - 网页正文部分左:
window.screenLeft
; - 屏幕分辨率的高:
window.screen.height
; - 屏幕分辨率的宽:
window.screen.width
; - 屏幕可用工作区高度:
window.screen.availHeight
; HTMLElement.offsetTop
为只读属性,它返回当前元素相对于其 offsetParent 元素的顶部的距离。window.innerHeigh
t:浏览器窗口的视口(viewport)高度(以像素为单位);如果有水平滚动条,也包括滚动条高度。
- 页可见区域宽:
图片预加载和懒加载比较:
- 两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。
- 懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力
常用插件
参考资料:
URL 拆解问题
题目描述
实现一个函数,可以对 url 中的 query 部分做拆解,返回一个 key: value 形式的 object
实例
输入:'http://sample.com/?a=1&e&b=2&c=xx&d#hash'
输出:
{a: 1, b: 2, c: 'xx', d: ''}
function getQueryObj(url) {
// TODO
let arr = url.split('?')[1].split('#')[0].split('&');
const res = {};
arr.forEach(e => {
const [key, value] = e.split('=');
if (!value) {
res[key] = '';
} else {
res[key] = value;
}
})
return res;
}
题目描述
实现一个 parseParam 函数,将 url 转化为指定结果
测试用例
输入:url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled'
输出:
{
user:'anonymous',
id:[123,456],// 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型
city:'北京',// 中文需解码
enabled: true // 未指定值的 key 与约定为 true
}
const parseParam = (url) => {
const arr = url.split('?')[1].split('&');
const res = {};
arr.forEach((e) => {
const [key, value] = e.split('=');
if (value === undefined) {
res[key] = true;
} else {
if (key in res) {
Array.isArray(res[key]) ? res[key].push(value) : res[key] = [res[key]].concat(value);
} else {
res[key] = decodeURI(value)
}
}
})
return res;
}
将 HTTP header 转换成对象
题目描述
实现一个方法,把 HTTP 文本形式(字符串)的 header 转换成 JS 对象。
测试用例
输入:
`Accept-Ranges: bytes
Cache-Control: max-age=6000, public
Connection: keep-alive
Content-Type: application/javascript`
输出:
{
"Accept-Ranges": "bytes",
"Cache-Control": "max-age=6000, public",
Connection: "keep-alive",
"Content-Type": "application/javascript"
}
解题思路:
- 首先将每行数据作为数组的一个元素
- 将每个元素使用冒号分割,前面为
key
,后面为value
。
const parseHeader = (s) => {
let res = {};
let arr = s.split("\n"); //获取单行字符串
arr.forEach((e) => {
let tmp = e.split(": ");
res[tmp[0]] = tmp[1];
})
return res;
}