jQuery 方法链 & var 意料之外
jQuery method chaining & var meaning unexpected
1) 代码看似简单,但方法链接不起作用:
$('.button').on('click', function(){
$(this).removeClass('shadow').delay(500).addClass('shadow');
});
2) 这个也不行:
$('.button').on('click' ,function() {
setTimeout(function() {
$(this).removeClass('shadow').addClass('shadow');
}, 500);
});
3) 但这个确实如此!
$('.button').on('click' ,function() {
var shadow = $(this).removeClass('shadow');
setTimeout(function() {
shadow.addClass('shadow');
}, 500);
});
请教有经验的码友:
1怎么了?
2 中已过时的 3 中的 var 执行了什么样的附加操作?这个案例颠覆了我对 var 的理解,因为我认为 var 只是某种数据持有者。
您的第一个片段不起作用,因为 .delay()
可用于延迟动画队列而不是其他人,即此处的 addClass
。
第二个片段的问题是,在 setTimeout
中,this
将指向 window。所以从技术上讲,您是从 window 中删除 class,而不是从您想要的元素中删除。为了克服这个问题,你可以做两件不同的事情,
您的第三个代码段正在运行,因为您不小心在那里创建了一个 closure
。因此,即使在执行了点击事件处理程序之后,您在 setTimeout
中使用的变量也会被保留。
对于这种情况更好的解决方案是,
将 setTimeout
外的 this
收集到 variable
中并在
内使用
$('.button').on('click' ,function() {
var $this = this.removeClass('shadow');
setTimeout(function() {
$this.addClass('shadow');
}, 500);
});
使用bind
改变setTimeout
,
的上下文
$('.button').on('click' ,function() {
$(this).removeClass('shadow');
setTimeout(function() {
$(this).addClass('shadow');
}.bind(this), 500);
});
或者最近的arrow function
,你可以这样,
$('.button').on('click' ,function() {
$(this).removeClass('shadow');
setTimeout(() => {
$(this).addClass('shadow');
}, 500);
});
.delay(time)
当队列中有动画时使用。但在您的情况下,您是 adding/removing 一个 property/attribute 值。
因此,您需要使用 setTimeout()
的延迟,例如:
$('.button').on('click', function(){
var $t = $(this);
$t.removeClass('shadow');
setTimeout(function(){ $t.addClass('shadow'); }, 500);
});
- 第一个问题是 adding/removing property/attribute 值未添加到队列中。
- 第二个问题是
setTimeout
中的匿名函数有自己的作用域,$(this)
不引用 $('.button')
.
- 第三个问题是您没有对
shadow
变量中元素的引用。如果您 var shadow = $(this);
检查下面,这很可能会起作用:
$('.button').on('click' ,function() {
var shadow = $(this);
shadow.removeClass('shadow');
setTimeout(function() {
shadow.addClass('shadow');
}, 500);
});
1) 代码看似简单,但方法链接不起作用:
$('.button').on('click', function(){
$(this).removeClass('shadow').delay(500).addClass('shadow');
});
2) 这个也不行:
$('.button').on('click' ,function() {
setTimeout(function() {
$(this).removeClass('shadow').addClass('shadow');
}, 500);
});
3) 但这个确实如此!
$('.button').on('click' ,function() {
var shadow = $(this).removeClass('shadow');
setTimeout(function() {
shadow.addClass('shadow');
}, 500);
});
请教有经验的码友: 1怎么了? 2 中已过时的 3 中的 var 执行了什么样的附加操作?这个案例颠覆了我对 var 的理解,因为我认为 var 只是某种数据持有者。
您的第一个片段不起作用,因为
.delay()
可用于延迟动画队列而不是其他人,即此处的addClass
。第二个片段的问题是,在
setTimeout
中,this
将指向 window。所以从技术上讲,您是从 window 中删除 class,而不是从您想要的元素中删除。为了克服这个问题,你可以做两件不同的事情,您的第三个代码段正在运行,因为您不小心在那里创建了一个
closure
。因此,即使在执行了点击事件处理程序之后,您在setTimeout
中使用的变量也会被保留。
对于这种情况更好的解决方案是,
将 setTimeout
外的 this
收集到 variable
中并在
$('.button').on('click' ,function() {
var $this = this.removeClass('shadow');
setTimeout(function() {
$this.addClass('shadow');
}, 500);
});
使用bind
改变setTimeout
,
$('.button').on('click' ,function() {
$(this).removeClass('shadow');
setTimeout(function() {
$(this).addClass('shadow');
}.bind(this), 500);
});
或者最近的arrow function
,你可以这样,
$('.button').on('click' ,function() {
$(this).removeClass('shadow');
setTimeout(() => {
$(this).addClass('shadow');
}, 500);
});
.delay(time)
当队列中有动画时使用。但在您的情况下,您是 adding/removing 一个 property/attribute 值。
因此,您需要使用 setTimeout()
的延迟,例如:
$('.button').on('click', function(){
var $t = $(this);
$t.removeClass('shadow');
setTimeout(function(){ $t.addClass('shadow'); }, 500);
});
- 第一个问题是 adding/removing property/attribute 值未添加到队列中。
- 第二个问题是
setTimeout
中的匿名函数有自己的作用域,$(this)
不引用$('.button')
. - 第三个问题是您没有对
shadow
变量中元素的引用。如果您var shadow = $(this);
检查下面,这很可能会起作用:
$('.button').on('click' ,function() {
var shadow = $(this);
shadow.removeClass('shadow');
setTimeout(function() {
shadow.addClass('shadow');
}, 500);
});