封装了一个处理时间的钩子函数,想用在多个地方,一个是界面头部,一个某一界面。在界面头部响应式生效了,但在另一个界面使用时却不生效,使用了watch和computed都没监听到变化:
(之前我的写法是每use一次都会创建定时器,那个时候响应式是正常的。后面我觉得定时器太多了就抽出来改成一个作为常量,就有了如上问题。)
界面头部使用:
<script lang="ts" setup>
import { useTime } from "@/hooks"
const { time } = useTime()
</script>
另一界面使用:
<script lang="ts" setup>
import { ref, watch } from "vue"
import { useTime } from "@/hooks"
const { time, timeStamp } = useTime()
watch(timeStamp, () => {
console.log("timetime", timeStamp)
})
</script>
钩子函数代码如下,这应该如何解决呢?
useTime
import { onMounted, ref, computed, onBeforeUnmount } from "vue";
import { Timer , clearSysTimer} from "@/utils";
export const useTime = () => {
const WEEK = ["日", "一", "二", "三", "四", "五", "六"];
// 分割时间
const timeSpliter = (time?: string | number): Array<number> => {
const current: Date = time ? new Date(time) : new Date();
const YYYY = current.getFullYear();
const MM = current.getMonth() + 1;
const DD = current.getDate();
const hh = current.getHours();
const mm = current.getMinutes();
const ss = current.getSeconds();
const week = current.getDay();
return [YYYY, MM, DD, hh, mm, ss, week];
};
// 填充零
const zeroPadder = (value: number | string): string => {
return value > 9 ? value.toString() : "0" + value;
};
// 时间格式化
const timeFormater = (format: string, time?: string | number): string => {
const [YYYY, MM, DD, hh, mm, ss, week] = timeSpliter(time);
const result = format
.replace("YYYY", `${zeroPadder(YYYY)}`)
.replace("MM", `${zeroPadder(MM)}`)
.replace("DD", `${zeroPadder(DD)}`)
.replace("hh", `${zeroPadder(hh)}`)
.replace("mm", `${zeroPadder(mm)}`)
.replace("ss", `${zeroPadder(ss)}`)
.replace("WEEK", `星期${WEEK[week]}`);
return result;
};
// 动态
const timeStamp = ref(); // 时间戳
const time = computed(() =>timeFormater("YYYY年MM月DD日 WEEK hh:mm:ss", timeStamp.value));
const refreshTime = () => {
timeStamp.value = new Date().getTime();
};
// 自增
const timerAdder = () => {
timeStamp.value += 1000;
};
onMounted(() => {
clearSysTimer()
refreshTime();
if(!Timer.localTimer){
Timer.localTimer= setInterval(() => {
timerAdder();
}, 1000);
}
if(!Timer.sysTimer){
Timer.sysTimer= setInterval(() => {
refreshTime();
}, 1000 * 60 * 5);
}
});
onBeforeUnmount(() => {
clearSysTimer()
});
return {
timeStamp,
timeSpliter,
timeFormater,
zeroPadder,
time,
refreshTime,
};
};
@/utils/index
export const Timer:{[index:string]:any}={
sysTimer:null,
localTimer:null
}
export const clearSysTimer=()=>{
clearInterval(Timer.sysTime)
clearInterval(Timer.localTime)
}
问题在 useTime 的这个 clearSysTimer
因为 Timer.localTimer 是全局唯一的,所以当 useTime 被第二次使用时,就会把第一个 useTime 中的定时器给清掉
这里如果你是想所有地方使用 useTime 都能获取到相同的一个倒计时,那么这里通过 发布订阅 来设计是比较合适的