为什么我的日期对象返回 NaN 值?

Why is my date object returning back NaN values?

这是我的 JS fiddle:

https://jsfiddle.net/apasric4/xkzwqr1m/1/

我的程序应该启动一个倒计时计时器,计算从今天到用户在输入字段中选择的日期的剩余时间(以天、小时、秒等为单位)。

当程序用正确的剩余时间更新 HTML 时,当我尝试每秒更新倒数计时器时问题就开始了。它 returns 出于某种原因返回 NaN 值。 为什么?

这是我的 JS:

const input = document.querySelector('input')
let timeInterval;
let timeStop;


input.addEventListener('change', (e) => {
    e.preventDefault()
    timeStop = true;
    endTime = Date.parse(e.target.value)
    updateHTML(endTime)
})


function updateHTML(endTime) {
  let time = calculateTimeDiff(endTime)
  if (time.total <= 0) {
    timeStop = false;
  }
  for (let pro in time) {
    let el = document.querySelector(`.${pro}`)
    if (el) {
      el.innerHTML = time[pro];
    }
  }
  updateCounter();
}


function updateCounter () {
  if (timeStop) {
    timeInterval = setInterval(updateHTML, 1000);
  } else {
    clearInterval(timeInterval);
  }
}

//returning time remaining till date in object form 
function calculateTimeDiff(endTime) {
  let start = Date.now();
  let end = endTime;
  let t = (end-start);
  let seconds = Math.floor((t / 1000) % 60);
  let minutes = Math.floor((t / 1000 / 60) % 60);
  let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
  let days = Math.floor(t / (1000 * 60 * 60 * 24));
  return {
    total: t,
    days: days,
    hours: hours,
    minutes: minutes,
    seconds: seconds
  }
}

当更新从事件开始时 - 一切正常

但稍后您使用 timeInterval=setInterval(updateHTML, 1000) - 并且 updateHTML 在没有参数 的情况下执行。改用真实日期,它会起作用

工作示例:

const input = document.querySelector('input')
let timeInterval;
let timeStop;
let savedTime;

input.addEventListener('change', (e) => {
  e.preventDefault()
  timeStop = true;
  endTime = Date.parse(e.target.value)
  updateHTML(endTime)
})

function updateHTML(endTime) {
  savedTime = endTime || savedTime;
  let time = calculateTimeDiff(savedTime)
  if (time.total <= 0) {
    timeStop = false
  }
  for (let pro in time) {
    let el = document.querySelector(`.${pro}`)
    if (el) {
      el.innerHTML = time[pro]
    }
  }
  updateCounter()
}

function updateCounter() {
  if (timeStop) {
    timeInterval = setInterval(updateHTML, 1000)
  } else {
    clearInterval(timeInterval)
  }
}

//returning time remaining till date in object form 
function calculateTimeDiff(endTime) {
  let start = Date.now()
  let end = endTime
  let t = (end - start)
  let seconds = Math.floor((t / 1000) % 60);
  let minutes = Math.floor((t / 1000 / 60) % 60);
  let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
  let days = Math.floor(t / (1000 * 60 * 60 * 24));
  return {
    total: t,
    days: days,
    hours: hours,
    minutes: minutes,
    seconds: seconds
  }
}
.time {
  display: inline-block;
  border-radius: 25%;
}
<!DOCTYPE html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="styles.css">
</head>

<body>

  <input type="date" name="endDate">
  <div class="clock">
    <div class="time"><span class="days">0</span> Days</div>
    <div class="time"><span class="hours">0</span> Hours</div>
    <div class="time"><span class="minutes">0</span> Minutes</div>
    <div class="time"><span class="seconds">0</span> Seconds</div>
  </div>


</body>

<script src="app.js"></script>

</html>

试试这个....

const input=document.querySelector('input')
let timeInterval;
let timeStop;
let endTime;

input.addEventListener('change', (e)=> {
  e.preventDefault()
  timeStop=true;
  endTime=Date.parse(e.target.value)
  updateHTML()
})


function updateHTML () {
  let time=calculateTimeDiff()
  if (time.total<=0) {
    timeStop=false
  }
  for (let pro in time) {
    let el=document.querySelector(`.${pro}`)
    if (el) {
      el.innerHTML=time[pro]
    }
  }
  updateCounter()
}


function updateCounter () {
  if (timeStop) {
    timeInterval=setInterval(updateHTML(), 1000)
  } else {
    clearInterval(timeInterval)
  }
}

//returning time remaining till date in object form 
function calculateTimeDiff () {
  let start=Date.now()
  let end=endTime
  let t=(end-start)
  let seconds = Math.floor((t / 1000) % 60);
  let minutes = Math.floor((t / 1000 / 60) % 60);
  let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
  let days = Math.floor(t / (1000 * 60 * 60 * 24));
  return {
    total: t,
    days: days,
    hours: hours,
    minutes: minutes,
    seconds: seconds
  }
}

所以您的代码工作正常,但您的问题出在 endTime 上。在您的 setInterval 中,您在调用 updateHTML 时没有使用参数 endTime,因此会导致错误,因为它没有参数的引用。

您可以简单地更新您的 updateCounter 函数以接受它作为参数并将其传递给您的 setInterval 函数:

function updateCounter (endTime) {
  if (timeStop) {
    timeInterval=setInterval(() => updateHTML(endTime), 1000)
  } else {
    clearInterval(timeInterval)
  }
}

然后在 updateHtml 函数底部使用 endTime 调用 updateCounter

或者,从 updateHtml 中删除作为参数的 endTime 并使其成为全局变量:

const input=document.querySelector('input')
let timeInterval;
let timeStop;
let endTime;


input.addEventListener('change', (e)=> {
  e.preventDefault()
  timeStop=true;
  endTime=Date.parse(e.target.value)
  updateHTML()
})


function updateHTML () {
  let time=calculateTimeDiff(endTime)
  if (time.total<=0) {
    timeStop=false
  }
  for (let pro in time) {
    let el=document.querySelector(`.${pro}`)
    if (el) {
      el.innerHTML=time[pro]
    }
  }
  updateCounter()
}


etc...

只需在代码中的函数 updateCounter() 中添加 preventDefault() 即可。 希望它会起作用。我试过了,它成功了。