最近在做的一个项目中,有一些点都不难但是还蛮有意思,特此来记录一番!

1. 实时动态计时

timer

这个需求并不难,最初稍微找了下有木有现成的组件,发现没有,可能是太简单了没有封装的必要。

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
export default {
data () {
return {
timer: null
}
}
created() {
this.timer = setInterval(this.updateCurrentTime, 1000) // 每秒更新当前时间
}
destroyed() {
clearInterval(this.timer) // 清除定时器
}
methods: {
updateCurrentTime() {
const now = new Date()
const difference = now - this.startTime // 计算当前时间与开始时间的时间差(毫秒)

// 计算经过的小时、分钟和秒数
let hours = Math.floor((difference / (1000 * 60 * 60)) % 24)
let minutes = Math.floor((difference / (1000 * 60)) % 60)
let seconds = Math.floor((difference / 1000) % 60)
hours = hours < 10 ? '0' + hours : hours
minutes = minutes < 10 ? '0' + minutes : minutes
seconds = seconds < 10 ? '0' + seconds : seconds
this.currentTime = hours < 1? `${minutes}:${seconds}` : `${hours}:${minutes}:${seconds}`
},
}
}

2. 屏幕的固定和适配

card
大概情况就是,在上面高度固定情况下,底部区域固定,中间区域高度动态并且超出滚动条显示。
滚动条很容易overflow:auto配合着高度height, 关键点就是这个高度怎么设置,固定写多少px肯定不行。
于是乎,经过一番研究,最终代码如下。

1
2
3
height: calc(100% - 260px);
max-height: calc((100vh - 400px));
overflow-y: auto;

利用calc(100% - 260px)根据设计图精准设置height, 在通过设置max-height: calc((100vh - 400px))来控制小屏时的height达到overflow-y: auto的效果。

小tips: calc中100%的对象是父容器,而其中的vh是整个屏幕

3. 滑动条位置控制

如上图中,当切上一题、下一题、或者点击进去某一题时滑动条位置不变或者到对应的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default {
methods: {
nextClick() {
localStorage.setItem("scrollPosition", this.$refs.questionsList.scrollTop);
...
...
...
if (localStorage.getItem("scrollPosition")) {
// 恢复滚动位置
this.$nextTick(() => {
this.$refs.questionsList.scrollTo(0, localStorage.getItem("scrollPosition"))
})
}
}
}
}

questionsList对应滚动条的区域, 上下题时通过localStorage记录滚动条的位置, 执行完逻辑后,根据记录的scrollTop, 设置对应滚动条位置。(一点要在$nextTick中设置哦)

4. 题目切换动画

初次听到这种,就感觉跟走马灯效果很相似,但是又不太一样。
太复杂的动画有没必要,直接把动画分解,只加入进入的动画,忽略退出的动画,达到简单的动态切换的效果。

1
2
3
4
5
6
7
8
export default {
methods: {
nextClick() {
this.$refs.questionArea.classList.add('fadeInRight')
setTimeout(() => {this.$refs.questionArea.classList.remove('fadeInRight')}, 1000)
}
}
}
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
@keyframes fadeInLeft {
from {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}

to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}

@keyframes fadeInRight {
from {
opacity: 0;
transform: translate3d(100%, 0, 0);
}

to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}

.fadeInRight {
animation: fadeInRight 1s;
}
.fadeInLeft {
animation: fadeInLeft 1s;
}

questionArea对应着动画的区域, 当点击上一题或者下一题时,添加动画class,然后动画执行完再移除class。

5. window.open重复打开同一个界面

1
2
3
4
5
6
7
if(this.newWindow && !this.newWindow.closed) {
this.newWindow.location.href = url;
this.newWindow.focus()
} else {
this.newWindow = window.open(url, "_blank", "")
this.newWindow.focus()
}