首页 > 解决方案 > 如何在不延迟的情况下正确获取 setInterval 内的某些元素宽度?

问题描述

我正在尝试使用setInterval. 当我测试时,它工作正常。

var progressBar = $('.progress-bar');

var count = 0;

var interval = setInterval(function () {
    var width = progressBar.width();

    console.log(width++);

    progressBar.width(width);

    count++;

    if (count === 101) {
      clearInterval(interval);
    }
}, 50);
.progress-bar {
  width: 0px;
  height: 4px;
  background-color: #00f;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<div class="progress-bar"></div>

由于我将它嵌套到下拉列表中,我在重复每个操作的时间上遇到了麻烦:

var increase = function (progressBar, ms) {
    var count = 0;

    var interval = setInterval(function () {
        var width = progressBar.width();

        console.log(width++);

        progressBar.width(width);

        count++;

        if (count === 21) {
          clearInterval(interval);
        }
    }, ms);
}

$('.dropdown').on('shown.bs.dropdown', function () {
    var progressBar = $(this).find('.progress-bar');
    
    increase(progressBar, +progressBar.data('ms'));
});
.progress-bar {
  width: 0px;
  height: 4px;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

<div class="dropdown d-inline-block">
  <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Progress bar with 100ms
  </button>
  <div class="dropdown-menu" >
    <a class="dropdown-item" href="#">
        <div class="progress-bar" data-ms="100"></div>    
    </a>
  </div>
</div>

<div class="dropdown d-inline-block">
  <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Progress bar with 300ms
  </button>
  <div class="dropdown-menu">
    <a class="dropdown-item" href="#">
        <div class="progress-bar" data-ms="300"></div>    
    </a>
  </div>
</div>

当我打开下拉菜单时,进度条的宽度会增加。但是当我尝试不同的值来重复操作时出现了问题。

在示例中,如果我将值设置为或更低,则会错误地100获取进度条宽度。默认宽度值是,增加后(通过添加),为什么是然后...?010.156250.3125

再试一次,如果我将值设置为或更高,我会正确300获得宽度(0、1、2 ...)

有谁知道为什么?

标签: javascriptjquerycssdrop-down-menu

解决方案


使用 css width 属性代替 od jQuerywidth()方法,因为width()可能返回不可靠的数据。

var increase = function (progressBar, ms) {
    var count = 0;
    var interval = setInterval(function () {
        var width = parseInt(progressBar[0].style.width) || 0;
        console.log(width++);
        progressBar[0].style.width = `${width}px`;
        count++;
        if (count === 21) {
          clearInterval(interval);
        }
    }, ms);
}

$('.dropdown').on('shown.bs.dropdown', function () {
    var progressBar = $(this).find('.progress-bar');
    
    increase(progressBar, +progressBar.data('ms'));
});
.progress-bar {
  width: 0px;
  height: 4px;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

<div class="dropdown d-inline-block">
  <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Progress bar with 100ms
  </button>
  <div class="dropdown-menu">
    <a class="dropdown-item" href="#">
      <div class="progress-bar" data-ms="100"></div>
    </a>
  </div>
</div>

<div class="dropdown d-inline-block">
  <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Progress bar with 300ms
  </button>
  <div class="dropdown-menu">
    <a class="dropdown-item" href="#">
      <div class="progress-bar" data-ms="300"></div>
    </a>
  </div>
</div>

取自文档

请注意, .width() 将始终返回内容宽度,无论 CSS box-sizing 属性的值如何。从 jQuery 1.8 开始,这可能需要检索 CSS 宽度加上 box-sizing 属性,然后当元素具有 box-sizing:border-box 时减去每个元素上的任何潜在边框和填充。为避免这种惩罚,请使用 .css("width") 而不是 .width()。


推荐阅读