1.主要使用原生的原理在vue中实现(自己拼接字符串)
<template>
<div>
<div>{{ times }}</div>
</div>
</template>
<script>
export default {
data() {
return {
times: "",
};
},
mounted() {
setInterval(() => {
var datetime = new Date();
var year = datetime.getFullYear();
var month =datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1): datetime.getMonth() + 1;
var date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
var hour = datetime.getHours() < 10 ? "0" + datetime.getHours():datetime.getHours();
var minutes = datetime.getMinutes() < 10 ? "0" + datetime.getMinutes():datetime.getMinutes();
var seconds = datetime.getSeconds() < 10 ? "0" + datetime.getSeconds():datetime.getSeconds();
this.times = year+" / " + month+" /" + date+" / "+ hour+" : " + minutes+" : " + seconds ;
console.log( this.times)
}, 1000);
},
};
</script>
- 这种写法,每秒都在更新这个字符串,但是实际上,每秒不是时分秒都在变化,所以实际上这种写法的性能不是很好,按需求,我们应该局部更新视图,所以我们可以按需,把时分秒做成一个组件,然后就变成按需渲染了
2.利用本地的时间表示方式(根据语言选择合适的显示方式)
<template>
<div>
<div>{{ times }}</div>
</div>
</template>
<script>
export default {
data() {
return {
times: "",
};
},
mounted() {
setInterval(() => {
this.times = new Date().toLocaleString();
}, 1000);
},
};
</script>
3.封装一个带有星期的时间
function getDate () {
const now = new Date()
const y = now.getFullYear()
const month = now.getMonth() + 1 < 10 ? '0' + (now.getMonth() + 1) : now.getMonth() + 1
const d = now.getDate() < 10 ? '0' + now.getDate() : now.getDate()
const h = now.getHours() < 10 ? '0' + now.getHours() : now.getHours()
const m = now.getMinutes() < 10 ? '0' + now.getMinutes() : now.getMinutes()
const s = now.getSeconds() < 10 ? '0' + now.getSeconds() : now.getSeconds()
const w = '星期' + '日一二三四五六'.charAt(now.getDay())
this.timeNow = h + ':' + m + ':' + s
this.weekNow = w
this.dataNow = y + '/' + month + '/' + d
return this.timeNow && this.weekNow && this.dataNow
}
4.moment插件
momentjs.com/
import moment from 'moment'
export const nowDate = {
data() {
return {
timeNow: '',
weekNow: '',
dataNow: '',
startDayTime: '',
endDayTime: '',
startWeekTime: '',
endWeekTime: '',
startMonthTime: '',
endMonthTime: '',
startYearTime: '',
endYearTime: '',
}
},
methods: {
getDate() {
this.timeNow = moment().format('HH:mm:ss')
this.weekNow = moment().isoWeekday()
this.dataNow = moment().format('YYYY/MM/DD')
this.startDayTime = moment().format('YYYY-MM-DD')
this.endDayTime = moment().add(1,'day').format('YYYY-MM-DD')
this.startWeekTime = moment().startOf('week').add(1,'day').format('YYYY-MM-DD')
this.endWeekTime = moment().endOf('week').add(1,'day').format('YYYY-MM-DD')
this.startMonthTime = moment().startOf('month').format('YYYY-MM-DD')
this.endMonthTime = moment().endOf('month').format('YYYY-MM-DD')
this.startYearTime = moment().startOf('year').format('YYYY-MM-DD')
this.endYearTime = moment().endOf('year').format('YYYY-MM-DD')
}
},
created() {
this.getDate()
}
}
- 如果想要正常显示“星期一”这种格式,需要简单处理一下
星期{{ week|getweek }}
filters: {
getweek(e) {
var week = ['一', '二', '三', '四', '五', '六', '日']
return week[e - 1]
},
},
5.注:什么是宏任务和微任务???
juejin.im/post/688078…
1.这里第一种和第二种实现方式,涉及的setInterval定时器,定时器任务是宏任务,因为是在不同的进程中进行的
2.就会有个问题,如果JS被阻塞了,JS后续的代码是不会被执行的,但是计时器会继续走
3.这样的话,每过1秒,定时器就会发出一个信号,要执行一下这个任务,这时候,因为JS的阻塞,其实信号接收也被阻塞了,或者说,即是收到了一堆任务,也无法立即执行
4.当时机切换到有剩余资源可以执行时,此时因为堆积了很多未执行的任务,所以会一下子把堆积的任务都执行掉,这就会造成一个可怕的结果,一瞬间造成大量的重绘
5.这里的重绘只有在原生和用setInterval的时候才会出现,为什么呢?
- 因为Vue的渲染设计的是微任务,大量堆积的任务执行时同步的,前面的定时器通知要执行这个动作是异步的,所以对于Vue来说,是不会造成大量的重绘的
- 但是this.times仍然会一下子被设置很多次,设置多次也就意味着经历了多次的Vue的劫持,Vue内部的逻辑也会一下子经历多次
- 这只是因为我在页面上显示的是实时时间,才不会造成问题
6.如果换成倒计时显示,很多人会设置每秒减1,这就会变成,当阻塞时,倒计时不动,阻塞时,倒计时不动是正常的,因为资源被占满了,不重绘也正常,但是,如果当有资源的话,一下子就会执行多次,就会看到屏幕上疯狂的倒计时递减,但其实,只要当有足够资源时,更新一次就行了,所以一种方法是可以用setTimeout替换setInterval
7.使用setTimeout+递归,替换setInterval,setTimeout仍然会有和setInterval一样的问题,但是会有个区别,因为setTimeout实现不断更新的逻辑是不停的循环调用自己,所以即使主线程阻塞,定时器只会通知一次,要执行回调,实际上,应该总是用setTimeout,尽量少用setInterval,原因是我们太容易遇到阻塞了
- 常见的阻塞场景:浏览器TAB页的切换,浏览器会挂起这个标签页的执行栈,也就是不在执行JS了,这个就相当于阻塞了
- 事件管理是不管标签页的,它有浏览器的时间管理统一管理,setInterval是让定时器每隔一段时间告诉主线程要执行任务了,然后调用自身说的是要用setTimeout实现setInterval的效果,肯定要写出递归的方法,调用自身
8.最后看宏任务的问题,哪怕已经改成了setTimeout,仍然会存在问题,问题在于两点:
- 宏任务因为存在资源的切换,所以设置的1秒后,肯定是大于等于1秒
- 开始的执行的实际不确定,因为你并不能保证程序执行的开始时间正好是整秒开始
9.因为上述两个问题,可能对于秒来说,感觉不出什么,但是对于分呢?因为在前端上来说,喵不是最小的单位,还可以获取到比秒更精确的数值,那么总应该使用更精确的方式去获取数据,前端能获取到的最小单位是高精度的微秒
10.所以如果实现一个秒表计时,用setTimeout和setInterval根本做不了,只能做到秒,但是秒后面的小数点该怎么做呢,要间隔多久更新一次呢?
11.我们无法知道要隔着多少秒去获取一下时间,因为时间时不断变化的,但是我们知道渲染的间隔,只要在每次渲染时去获取实时的精确的时间,所以,最好的方法,我们不应该使用宏任务,而应该使用微任务去做