我编写了这种简单的机制来向菜单添加一些交互性和效果:
var $body = $('body');
var $theNav = $('.the-nav-wrapper');
var $theMenuBar = $('.the-menu-bar');
var $menuOpener = $('.menu-opener');
$menuOpener.on('click', function() {
$(this).toggleClass('becomeMenuCloser textAppears');
$theNav.toggleClass('open');
$body.toggleClass('preventScroll');
$theMenuBar.toggleClass('bringOnTop');
$(this).toggleText('Menu', 'Close');
});
这很好。
在菜单编码的每一行中,我决定要在类becomeMenuCloser textAppears
的切换之间添加一个延迟,以便首先切换becomeMenuCloser
,然后在短暂的延迟之后切换{{ 1}}被切换。
我修改了负责切换类的特定代码行,如下所示:
textAppears
这不起作用。 它同时切换两个类。然后我尝试了这个:
$(this).toggleClass('becomeMenuCloser').delay(1300).toggleClass('textAppears');
这也不起作用。 然后我尝试了这个:
$(this).toggleClass('becomeMenuCloser').promise().done(function(){
$(this).toggleClass('textAppears');
});
这也不起作用,因为它的代码永远不会进入setTimeout,并且随后也不会切换第二个类。
经过反复试验(以及一些挫折和思考),我偶然发现解决我的问题的方法是删除$(this).toggleClass('becomeMenuCloser');
setTimeout(function() {
$(this).toggleClass('textAppears');
}, 610);
并将其替换为缓存的变量$(this)
,就像下面的代码一样:
$menuOpener
这有效。
问题是:
1)为什么在这种情况下$(this).toggleClass('becomeMenuCloser')
setTimeout(function() {
$menuOpener.toggleClass('textAppears');
}, 310);
是问题所在?我真的很想了解这里缺少的线索。
2)我也不明白为什么使用$(this)
可以解决问题。
3)当将元素存储为全局变量时,我是否应该仅使用全局变量并省略$menuOpener
?
嘿,谢谢!
答案 0 :(得分:2)
那是因为存在不同的上下文。
检查以下示例: Jsfiddle(click on the div text and check the console)
示例1: 在第一个功能中,第一个console.log打印
上下文1 id:foo
第二个打印时
上下文2 ID:未定义
由于上下文切换(不再指向dom元素)。
//example 1
function context() {
var div = $("#foo");
div.on('click', function() {
$(this).toggleClass('becomeMenuCloser');
console.log("context 1 id:" + this.id);//foo
setTimeout(function() {
console.log("context 2 id:" + this.id);//undefined
div.toggleClass('textAppears');
}, 610);
})
}
context();
现在,在第二个示例中,我们使用箭头功能(()=>
)保留上下文,因此在超时功能中也使用相同的“ this”实例,因此控制台两次都打印正确的ID。
在第一个功能中,第一个console.log打印
上下文1 id:foo
和第二个相同
上下文2 id:foo
//example 2
function context2() {
var div = $("#foo2");
div.on('click', function() {
$(this).toggleClass('becomeMenuCloser');
console.log("context 1 id:" + this.id);//foo
setTimeout(() => {
console.log("context 2 id:" + this.id);//foo
div.toggleClass('textAppears');
}, 610);
})
}
context2();