javascript - 为什么 Progress Bar 不像 Text 那样动态变化?

标签 javascript jquery css twitter-bootstrap settimeout

我在 setTimeout() 函数之后动态更新一些元素。 jQuery 函数 .text() 似乎在处理时随着数组索引的每次更改而动态更新。但是通过 .css().attr() 更改的 Bootstrap 进度条似乎不会动态更新。这是我的页面:http://imdbnator.com/process.php?id=f144caf0843490c0d3674113b03da0c5&redirect=false

您可以看到文本已更改,但进度条仅在整个 setTimeout() 函数完成后才结束。另外,如果我设置 delay = 1000。有用。但它会因应用程序而减慢。因此,我需要 delay = 0。但是为什么进度条没有变化呢?

这是我的代码

function launch(a) {
    var inc = 0;
    var maxc = a.length;
    var delay = 0; // delay milliseconds
    var iID = setInterval(function () {    
        var index = inc;
        var movie = a[inc];    
        //start processing function    
        //styling while processing                
        var markerPer = ((index + 1) / rawListNum) * 100; // marker percentage
        $("#procNum").text("(" + (index + 1) + "/" + rawListNum + ")"); //Processing number
        $("#procMovie").text(movie); //Processing Name
        $("div[role='progressbar']").css("width", markerPer + "%").attr("aria-valuenow", markerPer); // progress bar -> DOES NOT WORK    
        if (++inc >= maxc) clearInterval(iID);    
    },
    delay);
}

最佳答案

作为解释,很多答案都会指出这样一个事实,即大多数浏览器在UI线程上运行JavaScript,因此它们无法在执行JavaScript时更新界面。相反,浏览器将 wait for the Javascript to finish and return control to the UI thread .

虽然记住这一点很重要,但它对您的代码不起作用。如果您正在更新进度条,请执行以下操作:

for (i = 0; i < len; i++) {
    updateProgressBar(i)
};

那肯定会一直到最后才让UI不更新。

但是您已经通过使用 setTimeout 做了正确的事情或 setInterval ,它在代码中有异步回调。这意味着 JavaScript 能够暂停足够长的时间以通过管道输出任何 UI 消息。文本能够动态更新这一事实证明了这一点。

正如您的问题所问,如果 UI 正在更新,为什么进度条也没有更新?

答案在于 Bootstrap applies the following CSSprogress bar :

.progress-bar {
  -webkit-transition: width .6s ease;
       -o-transition: width .6s ease;
          transition: width .6s ease;
}

当调用之间的延迟为 0 毫秒时,浏览器确实有时间更新 UI,但没有有时间完成 600 毫秒的 CSS 过渡。因此,您直到结束才会看到动画。

作为OhAuth points out ,您可以通过使用 CSS 删除过渡效果来防止浏览器延迟宽度更新:

.progress .progress-bar {
  -webkit-transition: none;
       -o-transition: none;
          transition: none;
}

如果您循环浏览大量元素,增量更新将提供某种动画效果。如果您想保留通用用例的样式,您可以在代码中关闭和打开转换。截至jQuery 1.8 you can update CSS properties without the vendor prefix ,所以你只需要调用 .css("transition","none")

当然,根据您为每部电影所做的工作量,JavaScript 可能会在您可以直观地检测到所有 UI 更改之前完成,在这种情况下,延长延迟不会有什么坏处。如果您想测试运行时间更长的进程,可以使用以下 sleep function :

function sleep(sleepyTime) {
  var start = +new Date;
  while (+new Date - start < sleepyTime){}
}

这是一个您可以尝试的演示,其中每个设置都是一个变量,您可以配置该变量以查看它会如何 react ,但最好的办法是有条件地删除过渡。

堆栈片段中的演示

var delay, numMovies, throttledMovies, sleepTime, removeTransition;

$("#delay").change(function(){ delay = this.value }).change()
$("#movies").change(function(){ numMovies = this.value }).change()
$("#sleep").change(function(){ sleepTime = this.value }).change()
$("#transition").change(function(){ removeTransition = this.checked }).change()

$("#loadMovies").click(loadMovies);

function loadMovies() {
  var i = 0;
  
  throttledMovies = Movies.slice(0, numMovies)
  
  if (removeTransition) {
    $('#progress-bar-movie').css("transition","none");
  }
  
  var interval = setInterval(function () {
    loadMovie(i)

    if (++i >= numMovies) {
      clearInterval(interval);
      $('#progress-bar-movie').css("transition","width .6s ease");
    }
  }, delay);
};

function loadMovie(i) {
  var movie = throttledMovies[i];
  var percentComplete = ((i + 1) / numMovies) * 100;

  sleep(sleepTime);
  
  // update text
  $("#procNum").text("(" + (i + 1) + "/" + numMovies + ")");
  $("#procMovie").text(movie.Title); 

  // update progress bar
  $('#progress-bar-movie')
    .css('width', percentComplete+'%')
    .attr('aria-valuenow', percentComplete);
};

function sleep(sleepyTime) {
  var start = +new Date;
  while (+new Date - start < sleepyTime){}
}
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>
<script src="http://kylemitofsky.com/libraries/libraries/movies.js"></script>

<!-- params -->
<label for="delay">Delay (ms)</label>
<input type="number" value="0" min=0 max=1000 id="delay"/>
<label for="movies"># Movies </label>
<input type="number" value="250" min=0 max=250 id="movies"/>
<label for="sleep">Sleep time (ms)</label>
<input type="number" value="0" min=0 max=1000 id="sleep"/>
<label for="transition">Remove transition? </label>
<input type="checkbox" checked="true" id="transition"/><br/><br/>

<button class="btn btn-primary btn-lg" id="loadMovies">
  Load Movies
</button><br/><br/>

<p>
  <b>Current Title</b>: <span id="procMovie"></span><br/>
  <b>Progress</b>: <span id="procNum"></span>
</p>

<div class="progress">
  <div class="progress-bar" role="progressbar" id="progress-bar-movie" 
       aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>

关于javascript - 为什么 Progress Bar 不像 Text 那样动态变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30285185/

相关文章:

javascript - 无法在状态修改方法中访问状态对象的对象属性(TypeError)

javascript - 来自 BackboneJS 的 Ajax 调用

javascript - 在表单中添加行,只有第一个信息按钮打开

javascript - 如何提高图像交叉淡入淡出性能?

javascript - 同时使用 Angular 时调用 jQuery 函数

jquery - 如何制作带有播放和暂停按钮的自动幻灯片放映?

javascript - 有没有办法检测事件是使用输入设备触发还是通过 .onEvent() 中的脚本触发?

javascript - Jquery 错误 Uncaught TypeError Object has no method 'wijmenu'

html - Outlook 2010 中奇怪的表格格式

javascript - 对于 html2canvas 字体系列不起作用