Vue.js秒表页面刷新后自动增加6小时的技术求助
秒表刷新后自动额外增加6小时问题
我用Vue.js开发了一款秒表功能,点击按钮可启动计时,停止后将计时数据提交至Django模型。日常计时功能正常,但刷新页面后,秒表会自动额外增加6小时。
Vue.js 脚本
var NavbarApp = { data() { return { seconds: {{ active_entry_seconds }}, trackingTime: false, showTrackingModal: false, timer: null, entryID: 0, startTime: '{{ start_time }}' } }, delimiters: ['[[', ']]'], methods: { startTimer() { fetch('/apps/api/start_timer/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': '{{ csrf_token }}' } }) .then((response) => { return response.json() }) .then((result) => { this.startTime = new Date() this.trackingTime = true this.timer = setInterval(() => { this.seconds = (new Date() - this.startTime) / 1000 }, 1000) }) }, stopTimer() { fetch('/apps/api/stop_timer/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': '{{ csrf_token }}' } }) .then((response) => { return response.json() }) .then((result) => { this.entryID = result.entryID this.showTrackingModal = true this.trackingTime = false window.clearTimeout(this.timer) }) }, discardTimer() { fetch('/apps/api/discard_timer/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': '{{ csrf_token }}' } }) .then((response) => { this.seconds = 0 this.showTrackingModal = false }) }, addLater() { this.seconds = 0 this.showTrackingModal = false }, addToTask() { console.log('addToTask') window.location.href = '/apps/track_entry/' + this.entryID + '/' } }, mounted() { if (this.seconds !== 0) { this.trackingTime = true this.timer = setInterval(() => { this.seconds = (new Date() - new Date(this.startTime)) / 1000 }, 1000) } }, computed: { readableSeconds() { const d = Number(this.seconds); const h = Math.floor(d / 3600); const m = Math.floor(d % 3600 / 60); const s = Math.floor(d % 3600 % 60); const hDisplay = h > 0 ? h + (h == 1 ? "h, " : "h, ") : ""; const mDisplay = m > 0 ? m + (m == 1 ? "m, " : "m, ") : ""; const sDisplay = s >= 0 ? s + (s == 1 ? "s" : "s") : ""; return hDisplay + mDisplay + sDisplay; } } } Vue.createApp(NavbarApp).mount('#navbar-app')
HTML 代码
<div class="col-md-auto mt-md-0 mt-4" id="navbar-app"> <div class="hstack gap-1 flex-wrap"> <div class="navbar-item" v-if="!trackingTime"> <div class="buttons"> <button class="btn btn-success add-btn" @click="startTimer()"> Start Timer </button> </div> </div> <div class="navbar-item" v-else> <div class="buttons"> <div class="buttons"> <button class="btn btn-warning add-btn" @click="stopTimer()"> [[ readableSeconds ]] (stop) </button> </div> </div> </div>
现象说明
- 正常计时状态:点击启动后,秒表显示正确,例如显示
0h, 0m, 5s - 刷新页面后:秒表自动增加6小时,例如原本5秒变成
6h, 0m, 5s
问题分析与解决方案
核心原因
问题出在startTime的时区处理上:
- Django后端传递的
{{ start_time }}是服务器时区的时间字符串,前端用new Date(this.startTime)解析时,默认按照本地时区处理,导致时间差计算出现6小时的偏差(正好对应服务器与本地的时区差)。 mounted钩子中直接用本地时间与解析后的服务器时间计算差值,时区不统一导致秒数计算错误。
解决步骤
步骤1:后端传递UTC标准时间
修改Django后端,将start_time以UTC时间戳(毫秒)或带Z标识的ISO 8601格式字符串返回:
- 时间戳示例:
start_time = int(entry.start_time.timestamp() * 1000) - ISO格式示例:
start_time = entry.start_time.isoformat() + 'Z'(Z代表UTC时区)
步骤2:前端统一用UTC时间计算差值
修改Vue代码,确保所有时间计算基于绝对UTC时间,避免时区解析误差:
data() { return { // ...其他数据 startTime: {{ start_time_timestamp }} // 后端传递的UTC时间戳(数字类型) // 若用ISO格式则改为:startTime: '{{ start_time_iso_utc }}' } }, mounted() { if (this.seconds !== 0) { this.trackingTime = true const startTimeDate = typeof this.startTime === 'number' ? new Date(this.startTime) : new Date(this.startTime); this.timer = setInterval(() => { // 用Date.now()获取当前UTC时间戳,减去起始时间戳计算秒数 this.seconds = (Date.now() - startTimeDate.getTime()) / 1000 }, 1000) } }, startTimer() { // ...fetch请求部分 .then((result) => { this.startTime = Date.now() // 直接存储本地UTC时间戳 this.trackingTime = true this.timer = setInterval(() => { this.seconds = (Date.now() - this.startTime) / 1000 }, 1000) }) }
步骤3:验证逻辑一致性
确保启动计时、页面刷新恢复计时的逻辑,都使用UTC时间戳计算差值,彻底避免时区带来的时间偏差。
内容的提问来源于stack exchange,提问作者Langutang
相关产品推荐
相关产品推荐

