我今天写了第一个插件:一个简单的工具,可以使元素中的数字向上计数。 它工作得很好,但是我按照例子和一些反复试验来构建它,所以我不能说我理解它是如何完全运作的。
我不明白:
a)我应该如何包含secondsToTime()
函数之类的便捷函数(假设我需要它在一个函数中 - 我知道在这个例子中它没有。)为什么它在这里工作。每个街区?
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);
感谢您的反馈。
答案 0 :(得分:5)
a)我应该如何包括像secondsToTime()函数
这样的便利函数
我会在(function($) {
... })(jQuery);
函数中将其移出一个级别,因为不必为每个元素重新创建它。
a)...为什么它在这个块中起作用?
因为可以从在相同范围的范围内定义的代码或从嵌套范围访问函数。
b)我声明的变量(
_this
,seconds
,interval
)作用域是怎样的?
它们都是针对您传入this.each
的函数的每个调用所特有的。更具体地说:调用函数时,会创建调用的执行上下文。该执行上下文有一个变量对象,它包含在被调用的函数内声明的变量,函数参数和函数(所有函数都特定于函数调用等等)每次都创建)。您的updateTicker
函数(为每个调用创建)是对该变量对象的闭包,因此对这些变量有持久的引用。 (更多:Closures are not complicated。)
c)这个插件可以更好地构建吗?
this
创建一次jQuery对象然后重复使用它,而不是在开始时再进行两次,然后每次运行updateTicker
时再次使用它。例如,使var _this = this,
=&gt; var _this = $(this),
并在下一行和_this.text
内使用updateTicker
。parseInt
通常是一个好主意(否则,前导零可能会发生奇怪的事情)。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);
答案 1 :(得分:0)
改进代码示例@ T.JCrowder给出了。
以下是循环外的间隔,只运行一次。我们将时间作为整数存储在数据中,因此我们只需要parseInt一次。获取toTime函数以返回格式化的字符串。以及其他一些小改进。
(function($) {
$.fn.countup = MyNiftyPlugin_countup;
function MyNiftyPlugin_countup() {
var that = this;
function updateTicker(){
that.each(updateNode);
}
function updateNode() {
var $this = $(this); // cache
var seconds = $this.data("time") + 1; // get time from $.data
$this.data("time", seconds);
//var seconds = Date.now() // alternative get accurate time right _now_
var time = secondsToTime(seconds)[1]; // get string from tuple
$this.text(time).data("time", seconds);
}
setInterval(updateTicker, 1000);
updateTicker();
return this.each(function(){
var $this = $(this); // cache
$this.data("time", parseInt($this.text(), 10);
});
}
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 time = {
"h": hours,
"m": minutes,
"s": seconds
};
var outputtime = time.h + ":" + ((time.m <= 9) ? '0' + time.m : time.m) + ":" + ((time.s <= 9) ? '0' + time.s : time.s)
return [time, outputtime];
}
})(jQuery);