javascript - 管理在 JavaScript 中的动态元素中制作的计时器

标签 javascript jquery html css

实际上,我正在通过 AJAX 从数据库中检索一些数据,在检索数据时,我使用 JavaScript 在 HTML 中创建了一些动态元素。我在一个容器中创建了动态行,在该行中我创建了一个动态 div,其类是“col-md-4”,它是父行的子级,这意味着至少可以有 3 个类为“col-md-”的动态 div 4"在动态行中。为此,在 AJAX 的 obj.success 函数中使用了一个循环。使用循环在动态行中制作3个动态元素的目的。如果不使用循环,那么新行将只有一个 col-md-4 类的 div。

现在的问题是我从数据库中检索一些时间,然后获取当前时间我得到两个时间的差异,然后使用一个函数来运行时间。这一切都是循环。现在的问题是计时器只对行中的最后一个元素运行。 我在另一个场景中使用了计时器,但是没有问题,因为在那个场景中没有使用循环。

var ajax = prompt('Confirm demo or paste AJAX data', '[ {"id":1}, {"id":2}, {"id":3}, {"id":4}, {"id":5}]');
display(ajax);
function display(response) {
    var n=1;
    var times = ["2019-09-19 12:59","2019-09-27 12:59","2019-12-19 12:59","2019-11-19 12:59","2019-10-19 12:59"];
    var time=new Date().toLocaleTimeString('en-GB');
           var res = time.slice(0,-3);
    var today = new Date();
        var dd = String(today.getDate()).padStart(2, '0');
        var mm = String(today.getMonth() + 1).padStart(2, '0'); 
        var yyyy = today.getFullYear();
        today = yyyy + '-' + mm + '-' + dd;
        var current=today+" "+res;
      //  alert(current);
    var data = JSON.parse(response);
    if(data.length) {
        for(var i=0;i<data.length;i++) {
            var parent= document.getElementsByClassName('carousel')[0];
            var row1= document.createElement("div");
            row1.setAttribute("class", "row");
            row1.setAttribute("id", "row"+n);
            parent.appendChild(row1);
            var crow1;
            for(var j=0;j<3 && i+j < data.length;j++) {
              crow1 = document.createElement("div");
              crow1.setAttribute("class", "col-md-4");
              crow1.setAttribute("id", data[i+j].id);
              crow1.innerText = "data" + (i+j)+" ";
              row1.appendChild(crow1);
              var distance = (new Date(times[0])).getTime() - (new Date(current)).getTime();
              var lmn = Math.floor(Math.random() *999999999999);
               var timer = document.createElement("h");
                            timer.setAttribute("id",lmn);
                            crow1.appendChild(timer);
                        var x = setInterval(function() {
                        var days = Math.floor(distance / (1000 * 60 * 60 * 24));
                        var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
                        var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
                        var seconds = Math.floor((distance % (1000 * 60)) / 1000);
                        
                        document.getElementById(lmn).innerHTML =days + "days " + hours + "hours " + minutes + "mins " + seconds + "secs ";
                            distance -= 1000;
                     if (distance < 0) {
                    clearInterval(x);
                    document.getElementById(lmn).innerHTML = "¡El tiempo de partida ha comenzado!";

                }
            }, 1000);
            }
            i += 3-1;
            n++;
        }

    }
}
DIV.col-md-4 {
  display: inline;
  background-color: #FF0080;
  margin: 5px;
}
.row {
  display: block;
  background-color: #80E080;
  padding: 3px;
}
<div class="carousel">
</div>

为什么只有最后一个元素显示计时器?

最佳答案

您遇到的行为是同步工作流问题中的典型异步函数。在您的 setInterval 回调中,您使用的是值 lmn。当回调函数访问此变量时,代码流将循环遍历循环,lmn 将保留最大循环索引值。

因此,为了解决这个问题,您将异步函数包含在一个闭包函数调用中,并将在该回调中使用的变量(在异步方法外部设置)发送回作为该闭包调用的参数。检查下面的代码示例,我已经用闭包调用更新了它。

为了更好地理解这是如何工作的,请在您的调试控制台中放置一个检查点,该检查点位于您在异步回调中使用 lmn 变量的位置,有和没有闭包调用。

要了解有关闭包的更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

var ajax = prompt('Confirm demo or paste AJAX data', '[ {"id":1}, {"id":2}, {"id":3}, {"id":4}, {"id":5}]');
display(ajax);

function display(response) {
var n = 1;
var times = ["2019-09-19 12:59", "2019-09-27 12:59", "2019-12-19 12:59", "2019-11-19 12:59", "2019-10-19 12:59"];
var time = new Date().toLocaleTimeString('en-GB');
var res = time.slice(0, -3);
var today = new Date();
var dd = String(today.getDate()).padStart(2, '0');
var mm = String(today.getMonth() + 1).padStart(2, '0');
var yyyy = today.getFullYear();
today = yyyy + '-' + mm + '-' + dd;
var current = today + " " + res;
//  alert(current);
var data = JSON.parse(response);
if (data.length) {
    for (var i = 0; i < data.length; i++) {
        var parent = document.getElementsByClassName('carousel')[0];
        var row1 = document.createElement("div");
        row1.setAttribute("class", "row");
        row1.setAttribute("id", "row" + n);
        parent.appendChild(row1);
        var crow1;
        for (var j = 0; j < 3 && i + j < data.length; j++) {
            crow1 = document.createElement("div");
            crow1.setAttribute("class", "col-md-4");
            crow1.setAttribute("id", data[i + j].id);
            crow1.innerText = "data" + (i + j) + " ";
            row1.appendChild(crow1);
            var distance = (new Date(times[0])).getTime() - (new Date(current)).getTime();
            var lmn = Math.floor(Math.random() * 999999999999);
            var timer = document.createElement("h");
            timer.setAttribute("id", lmn);
            crow1.appendChild(timer);
            (function(l, d){
              var x = setInterval(function() {
                  var days = Math.floor(d / (1000 * 60 * 60 * 24));
                  var hours = Math.floor((d % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
                  var minutes = Math.floor((d % (1000 * 60 * 60)) / (1000 * 60));
                  var seconds = Math.floor((d % (1000 * 60)) / 1000);

                  document.getElementById(l).innerHTML = days + "days " + hours + "hours " + minutes + "mins " + seconds + "secs ";
                  d -= 1000;
                  if (d < 0) {
                      clearInterval(x);
                      document.getElementById(l).innerHTML = "¡El tiempo de partida ha comenzado!";

                  }
              }, 1000);

            })(lmn, distance); // This is called a closure function, use this when you are using async methods in synchronous code blocks
        }
        i += 3 - 1;
        n++;
    }

}
}
DIV.col-md-4 {
  display: inline;
  background-color: #FF0080;
  margin: 5px;
}
.row {
  display: block;
  background-color: #80E080;
  padding: 3px;
}
<div class="carousel">
</div>

关于javascript - 管理在 JavaScript 中的动态元素中制作的计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57998265/

相关文章:

javascript - 如何基于 widgetVar 在 Primefaces 组件中查找和/或覆盖 JavaScript?

javascript - Javascript中For Loop不会退出,无限循环

jquery - 如何在单击除 div 以外的任何地方时关闭 div?

javascript - 单击浏览器滚动条关闭弹出窗口

javascript - 视差效果 - 强制文本 block 表现得像背景附件 : fixed

javascript - 仅从列表 jquery 中显示选定的元素

javascript - 如何在旧评论后面显示新评论?

javascript - 如何将多个ID转换为一个类?

html - 如何在 HTML 表单文本框中输入尖括号,这样它们就不会在 'sanitized' 之外

jquery - 如何比较两个 XML 并在网页上显示它们的差异?