仿照 driver.js 实现 新手指引的功能
实现思路是:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新手指引功能</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
box-sizing: border-box;
}
.stepBlock {
background-color: burlywood;
margin-right: 20px;
}
.positionStyle {
position: absolute;
z-index: 200;
}
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .5);
z-index: 100;
}
</style>
</head>
<body>
<section id="mask">
<!-- 存储提示语 -->
<section class="positionStyle" id="tip"></section>
<!-- 存储 高亮的第一步、第二步、第三步-->
<section class="positionStyle" id="curStepMask"></section>
</section>
<section style="margin:200px;">
<span id="first" class="stepBlock">第一步</span>
<span id="second" class="stepBlock">第二步</span>
<span id="third" class="stepBlock">第三步</span>
</section>
<section style="margin-top:30px">
<button onclick="setMask()">开始指引</button>
</section>
<script>
const tipDict = [
{id: 'first', content: '这里是第1步哦'},
{id: 'second', content: '这里是第2步哦'},
{id: 'third', content: '这里是最后一步哦,点击完成按钮结束新手指引'},
]
let flag = 0;
// 添加蒙层
function setMask() {
let mask = document.getElementById('mask')
mask.setAttribute('class', 'overlay')
setTip()
}
// 移除蒙层
function removeMask() {
let mask = document.getElementById('mask')
mask.setAttribute('class', '')
// 移除tip提示的子元素
removeTip()
removeStepMask()
}
function setTip() {
if (flag < tipDict.length) {
// 获取当前步骤的元素,以及元素的位置信息,供后续定位提示信息和覆盖信息使用
const curStepEle = document.getElementById(tipDict[flag].id)
const bound = curStepEle.getBoundingClientRect()
// 找到 id 为 tip 的元素
let ele = document.getElementById("tip")
// 如果存在子元素,先移除
removeTip()
removeStepMask()
// 创建提示信息和下一步的统一父元素,方便后续移除元素
let node = document.createElement('div')
// 创建提示信息
let tipText = document.createTextNode(tipDict[flag].content)
// 将提示信息插入到父元素
node.appendChild(tipText)
// 创建“下一步”按钮
let nextBtn = document.createElement('button')
nextBtn.innerHTML = flag === tipDict.length - 1 ? '完成' : '下一步';
nextBtn.onclick = setTip;
// 将按钮插入到父元素
node.appendChild(nextBtn)
// 设置统一父元素的位置
ele.style.left = bound.x + 'px'
ele.style.top = bound.y + 20 + 'px'
// 将创建的提示语元素插入到id为tip的元素
ele.appendChild(node)
// 将当前步骤高亮显示
let tag = flag - 1
if (tag >= 0) {
document.getElementById(tipDict[tag].id).style = ''
}
// const curStepEle = document.getElementById(tipDict[flag].id)
// const bound = curStepEle.getBoundingClientRect()
const curStepMask = document.getElementById('curStepMask')
curStepMask.style.left = bound.x + 'px'
curStepMask.style.top = bound.y + 'px'
const curStepEleClone = curStepEle.cloneNode(true)
curStepMask.appendChild(curStepEleClone)
flag++
} else {
flag = 0;
removeMask()
}
}
function removeStepMask() {
let ele = document.getElementById('curStepMask')
let child = ele.lastElementChild
if (child) {
ele.removeChild(child)
}
}
function removeTip() {
let ele = document.getElementById("tip")
let child = ele.lastElementChild
if (child) {
ele.removeChild(child)
}
}
</script>
</body>
</html>返回值是一个
DOMRect对象,是包含整个元素的最小矩形(包括padding和border-width)。该对象使用left、top、right、bottom、x、y、width和height这几个以像素为单位的只读属性描述整个矩形的位置和大小。除了width和height以外的属性是相对于视图窗口的左上角来计算的。 --MDN

在 localStorage 中存储用户关闭公告栏的时间戳,等再次进入页面的时候判断是不是存在 localStorage:
function getTime(data, type){ //data 时间戳,type 返回的类型默认 Y,可传参 Y 和 H
let time = new Date(data);
let Y = time.getFullYear();//获得年
let Mon = time.getMonth() + 1; //月
let Day = time.getDate();//日
let H = time.getHours();
let Min = time.getMinutes();
let S = time.getSeconds();
//自定义选择想要返回的类型
if(type === "Y") { //返回年月日2020-10-10
return `${Y}-${Mon}-${Day}`
} else if(type === "H") { //返回时分秒20:10:10
return `${H}:${Min}:${S}`
} else { //返回年月日时分秒2020-10-10 10:26:38
return `${Y}-${Mon}-${Day} ${H}:${Min}:${S}`
}
}命名方式中划线改小驼峰
function transName(arr) {
let res = arr.map(e => {
let items = e.split('-').map((item, index) => {
if (index) {
let first = item.substring(0,1)
let rest = item.substring(1)
return first.toUpperCase()+rest
}else{
return item.toLowerCase()
}
})
return items.join('')
})
return res
}
console.log(transName(['A-b-cee', 'ca-de-ea', 'e-fe-eaa','f-g','mn']))
// ['aBCee', 'caDeEa', 'eFeEaa', 'fG', 'mn']function turnName(str){
return str.replace(/-[a-zA-Z]/g,match=>match.replace('-','').toUpperCase())
}命名方式小驼峰改中划线
let s1 = 'aBBcdE';
let t = s1.replace( /[A-Z]/g, match=>'-'+match.toLowerCase());
console.log(t);分为强缓存和协商缓存
强缓存不需要客户端向服务端发送请求,有两种响应头实现方案:
强缓存过期之后会使用协商缓存,协商缓存需要客户端向服务端发送请求,资源未过期则服务端返回 304,否则返回新的资源。协商缓存也有两种实现方案:
Last-Modified 表示本地文件最后修改日期,If-Modified-Since 会将 Last-Modified 的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。但是如果本地文件被打开,会导致Last-Modified 被修改。ETag 类似于文件指纹,If-None-Match 会将当前 ETag 发送给服务器,询问该资源 ETag 是否变动,有变动的话就将新的资源发送回来。并且 ETag 优先级比 Last-Modified 高方案1:clientHeight + scrollTop > offsetTop
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片加载优化</title>
</head>
<body>
<div style="background-color: green;width:100vw;height:8000px">
</div>
<div id="yellow" style="background-color: yellow;width:100vw;height:800px">
</div>
<script>
document.addEventListener('scroll', () => {
// 获取屏幕可视区域的高度
const clientH = document.documentElement.clientHeight
// 获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离
const scrollT = document.documentElement.scrollTop
// 获取元素相对于文档顶部的高度
const offsetTop = document.getElementById('yellow').offsetTop
if (clientH + scrollT > offsetTop) {
console.log('进入可视区域啦!!')
}
})
</script>
</body>
</html>方案2:下滑过程中 bound.top 会越来越小
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片加载优化</title>
</head>
<body>
<div style="background-color: green;width:100vw;height:8000px">
</div>
<div id="yellow" style="background-color: yellow;width:100vw;height:800px">
</div>
<script>
document.addEventListener('scroll', () => {
var bound = document.getElementById('yellow').getBoundingClientRect(); // 获取元素的大小及位置
var clientHeight = window.innerHeight;
if (bound.top <= clientHeight) {
console.log('进入可视区域啦')
}
})
</script>
</body>
</html>