You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel8切换页面时JS倒计时重置及waktu未定义报错求助

问题原因

两个问题的根源分别是:

  • Uncaught ReferenceError: waktu is not defined报错:waktu被定义在$.get异步回调的局部作用域内,且$.get是异步执行,代码运行到计算deadline的位置时,回调还没执行,全局作用域下访问不到waktu变量就会报错。另外原代码里var waktu = $("#timer").html(topic);的写法本身逻辑错误,既没有id为timer的DOM元素,赋值拿到的还是jQuery对象不是数值。
  • 切换页面倒计时重置:传统页面跳转时会销毁当前页面的所有JS运行环境,内存中的变量全部清空,原代码每次页面加载都基于当前时间重新计算截止时间,自然会回到初始值重新计数。
修复步骤

1. 调整后端控制器逻辑

去掉从请求参数取timer值的逻辑,直接在后端固定初始倒计时时长,避免前端篡改参数作弊,把初始值直接传给模板:

public function show(Request $request, $id)
{
    $datas = Q_Question::where('topic_id', '=', $id)->simplePaginate(1);
    $topic = Q_Topic::where('id', '=', $id)->first();
    // 此处设置初始倒计时总分钟数,例如限制访问30分钟则填30,可按需修改
    $topic->timer = 30;
    return view('qanswers.show', compact('datas', 'topic'));
}

2. 修改Blade模板

在模板的<head>区域新增meta标签,用于把后端传的初始时长输出到前端,同时保留原有的倒计时DOM结构即可:

<meta name="initial-timer" content="{{ $topic->timer }}">
<!-- 原有倒计时DOM结构保持不变 -->
<div class="col-md-2">
    jam : 
    <div id="clockdiv">
        <div>
            <span class="days"></span>
            <div class="smalltext">Days</div>
        </div>
        <div>
            <span class="hours"></span>
            <div class="smalltext">Hours</div>
        </div>
        <div>
            <span class="minutes"></span>
            <div class="smalltext">Minutes</div>
        </div>
        <div>
            <span class="seconds"></span>
            <div class="smalltext">Seconds</div>
        </div>
    </div>
</div>

3. 替换原有JS代码

删除原有无效的$.get请求逻辑,改用localStorage存储统一的截止时间戳,同域名下所有页面共享该值,从根源解决跨页面重置问题,同时修复变量作用域报错:

function getTimeRemaining(endtime) {
  const t = Date.parse(endtime) - Date.parse(new Date());
  const seconds = Math.floor((t / 1000) % 60);
  const minutes = Math.floor((t / 1000 / 60) % 60);
  const hours = Math.floor((t / (1000 * 60 * 60)) % 24);
  const days = Math.floor(t / (1000 * 60 * 60 * 24));
  return {
    'total': t,
    'days': days,
    'hours': hours,
    'minutes': minutes,
    'seconds': seconds
  };
}

function initializeClock(id, endtime) {
  const clock = document.getElementById(id);
  const daysSpan = clock.querySelector('.days');
  const hoursSpan = clock.querySelector('.hours');
  const minutesSpan = clock.querySelector('.minutes');
  const secondsSpan = clock.querySelector('.seconds');
  const timeinterval = setInterval(updateClock, 1000);

  function updateClock() {
    const t = getTimeRemaining(endtime);
    // 倒计时归0处理
    if (t.total <= 0) {
      clearInterval(timeinterval);
      localStorage.removeItem('countdown_deadline');
      // 此处可添加超时后的业务逻辑,例如跳转到超时提示页
      // window.location.href = '/timeout';
      daysSpan.innerHTML = 0;
      hoursSpan.innerHTML = '00';
      minutesSpan.innerHTML = '00';
      secondsSpan.innerHTML = '00';
      return;
    }

    daysSpan.innerHTML = t.days;
    hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
    minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
    secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
  }

  updateClock();
}

document.addEventListener('DOMContentLoaded', function() {
  let deadline;
  // 优先读取本地存储的截止时间,存在则直接复用
  const storedDeadline = localStorage.getItem('countdown_deadline');
  if (storedDeadline) {
    deadline = new Date(Number(storedDeadline));
  } else {
    // 无存储时读取初始时长计算截止时间,并存入本地存储
    const initialMinutes = Number(document.querySelector('meta[name="initial-timer"]').content);
    deadline = new Date(Date.now() + initialMinutes * 60 * 1000);
    localStorage.setItem('countdown_deadline', deadline.getTime().toString());
  }
  initializeClock('clockdiv', deadline);
});
补充说明
  • localStorage数据持久化存储在浏览器本地,同域名下页面切换、刷新都不会丢失,因此倒计时会持续累计不会重置
  • 如果需要手动重置倒计时(例如用户主动退出访问、提交表单后),在对应触发逻辑中执行localStorage.removeItem('countdown_deadline');即可
  • 初始时长固定在后端返回,避免前端篡改参数延长访问时长,安全性更高

内容的提问来源于stack exchange,提问作者indahwati indahwati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 23:36:17