我的第一个jQuery插件.需要帮助格式化并了解其工作原理

doc*_*nge 4 javascript jquery plugins

我今天写了我的第一个插件:一个简单的工具,使元素中的数字向上计数.它工作得很好,但我按照例子和一些试验和错误构建它,所以我不能说我理解它是如何完全工作的.

我不明白:

a)我应该如何包括像函数一样的方便函数secondsToTime()(假设我需要它在函数中 - 我理解在这个例子中它没有.)为什么它在this.each块中起作用?

b)我声明(_this, seconds, interval)作用域的变量是怎样的?每个元素都保持同时存在.

c)这个插件可以更好地构建吗?

码:

$(document).ready(function(){
  $('.ticker').countup();
});

(function($) {   
  $.fn.countup = function() {
    return this.each(function(){
      var _this = this,
      seconds = parseInt($(this).text()),
      interval = setInterval(updateTicker, 1000 );
      updateTicker();
      function updateTicker(){
        seconds += 1;
        time = secondsToTime(seconds);
        outputtime = time.h + ":" + ((time.m <= 9) ? '0' + time.m : time.m) + ":" + ((time.s <= 9) ? '0' + time.s : time.s)
        $(_this).text(outputtime);
      }   
      function secondsToTime(secs){
        var hours = Math.floor(secs / (60 * 60));
        var divisor_for_minutes = secs % (60 * 60);
        var minutes = Math.floor(divisor_for_minutes / 60);
        var divisor_for_seconds = divisor_for_minutes % 60; 
        var seconds = Math.ceil(divisor_for_seconds);
        var obj = { 
          "h": hours,
          "m": minutes,
          "s": seconds
        };  
        return obj;
      }   
    }); 
  };  
})(jQuery); 
Run Code Online (Sandbox Code Playgroud)

感谢您的反馈意见.

T.J*_*der 5

a)我应该如何包括像secondsToTime()函数这样的方便函数

我会将它移出你的(function($) {... })(jQuery);函数中的一个级别,因为它不必为每个元素重新创建.

a)...为什么它在这个块中起作用?

因为可以从在相同作用域级别定义的代码或嵌套作用域中访问函数.

B)如何为我声明的变量(_this,seconds,interval作用域)?

它们都是针对您传入的函数的每个调用所特有的this.each.更具体地说:当调用函数时,创建调用的执行上下文.该执行上下文有一个变量对象,它包含在被调用的函数内声明的变量,函数参数和函数(所有这些都是特定于函数调用的,因此每次都会创建).您的updateTicker函数(为每个调用创建)是对该变量对象的闭包,因此具有对这些变量的持久引用.(更多:闭包并不复杂.)

c)这个插件可以更好地构建吗?

  1. 见上文(a).
  2. 我可能会使我的插件函数成为命名函数而不是匿名函数.(更多:Anonymousouses anonymous)你已经拥有了你的包装函数(我在上面的(a)中提到的那个),所以它不会花费你任何东西,但是当函数实际上有名字时它会使调试更容易.
  3. 我可能只创建this一次jQuery对象然后重用它,而不是在开始时再做两次然后每次updateTicker运行再次.例如,make var _this = this,=> var _this = $(this),_this.text在下一行和内部使用updateTicker.
  4. parseInt通过提供第二个参数来强制基数是一个好主意(否则,前导零可能会发生奇怪的事情).
  5. 您可以考虑仅使用一个间隔计时器来更新所有元素,而不是每个元素的间隔.
  6. 我想添加一种方法来停止更新.
  7. 请注意,计时器根本不精确,因此您的倒计时可能会有所不同.您可以考虑抓住开始时间并计算它实际存在的时间,而不是递减该seconds值.

这是第一次执行上面的#1 - #4,让其他人为你做:

(function($) {   

  $.fn.countup = MyNiftyPlugin_countup;               // #2

  function MyNiftyPlugin_countup() {                  // #2 cont'd
    return this.each(function(){
      var _this = $(this),                            // #3
          seconds = parseInt(_this.text(), 10),       // #3 cont'd, #4
          interval = setInterval(updateTicker, 1000 );

      updateTicker();

      function updateTicker(){
        seconds += 1;
        time = secondsToTime(seconds);
        outputtime = time.h + ":" + ((time.m <= 9) ? '0' + time.m : time.m) + ":" + ((time.s <= 9) ? '0' + time.s : time.s)
        _this.text(outputtime);                       // #3 cont'd
      }   
    }); 
  }

  function secondsToTime(secs){                       // #1 (moving this out a level)
    var hours = Math.floor(secs / (60 * 60));
    var divisor_for_minutes = secs % (60 * 60);
    var minutes = Math.floor(divisor_for_minutes / 60);
    var divisor_for_seconds = divisor_for_minutes % 60; 
    var seconds = Math.ceil(divisor_for_seconds);
    var obj = { 
      "h": hours,
      "m": minutes,
      "s": seconds
    };  
    return obj;
  }   
})(jQuery); 
Run Code Online (Sandbox Code Playgroud)