element.on('click focus', function (e) {
// Do Something
}
在我的示例中,do something 将运行两次。我希望每次交互只运行一次。
我正在使用焦点,因此用户可以进入元素以触发事件或单击它以触发事件。
如果用户多次与之交互(打开,然后关闭,然后再次打开),则可以多次触发该事件。
我的想法是这种行为是错误的,但是从您在这里的描述来看,这是处理您为菜单详细说明的事件的一般想法。在这里工作演示:https://jsfiddle.net/mcso7q1y/
HTML:
<button id="btn">Click Me</button>
<ul id="menu">
<li>This is a menu.</li>
<li>This is a menu.</li>
<li>This is a menu.</li>
<li>This is a menu.</li>
</ul>
j查询:
$(document).ready(function(){
$("#menu").slideUp("fast");
var closed = true;
$("#btn").click(function(){
menuToggle(closed);
closed = !closed;
});
$("#btn").focus(function(){
menuToggle(closed);
closed = !closed;
});
$("#btn").focusout(function(){
menuToggle(closed);
closed = !closed;
});
});
function menuToggle(clsd){
if(clsd){
$("#menu").slideDown();
} else {
$("#menu").slideUp();
}
}
您可以滚动自己的方法来处理多个事件,使用轻微的超时来限制事件,因此只会触发一个事件等。
$.fn.onMulti = function() {
var temp = [].slice.call(arguments), fn = temp.pop();
return this.on(...temp, function() {
clearTimeout($(this).data('multiTimer'));
$(this).data('multiTimer', setTimeout(fn.bind(this, arguments), 200))
});
}
$.fn.onMulti = function() {
var temp = [].slice.call(arguments), fn = temp.pop();
return this.on(...temp, function() {
clearTimeout($(this).data('multiTimer'));
$(this).data('multiTimer', setTimeout(fn.bind(this, arguments), 200))
});
}
/* To be used like */
var element = $('a'), i = 0;
element.onMulti('click focus', function(e) {
console.log('works : ' + (++i));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#">Active Element Anchor, fires events on click and focus</a>
<br />
<br />
<br />
<div>Element to click on to remove focus</div>
创建一个名为
done
的变量,如果 false
是 done
并且在函数结束时将 false
更改为 done
如果函数 get 再次触发 'Do Something' 将不会被执行,因为 'done' 设置为 true
true
var done = false;
element.on('click focus', function (e) {
if( !done ) {
// Do Something
}
done = !done;
}
$(function() {
function Menu(element) {
this.isOpen = false;
this.element = element;
$(this.element).on('focusin', this.open.bind(this));
$(this.element).on('focusout', this.close.bind(this));
$(this.element).on('click', this.open.bind(this));
}
Menu.prototype.open = function() {
this.isOpen = true;
this.update();
}
Menu.prototype.close = function() {
this.isOpen = false;
this.update();
}
Menu.prototype.update = function() {
$(this.element).toggleClass('open', this.isOpen);
}
$('.item').each(function (ix, el) { new Menu(el); });
});
.item .submenu {
display: none;
}
.item.open .submenu {
display: block;
}
您可能想考虑编写一个 jQuery 插件而不是所有这些插件(或使用许多现有插件之一)。
如果您使用 addEventListener()
而不是 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="item"><a href="#">Menu</a>
<ul class="submenu">
<li>Submenu</li>
<li>Submenu</li>
</ul>
</li>
<li class="item"><a href="#">Menu</a>
<ul class="submenu">
<li>Submenu</li>
<li>Submenu</li>
</ul>
</li>
</ul>
,您可以像这样在纯 JavaScript 中执行此操作:
.on(event, fn)
解释:
当一个元素被点击或获得焦点时,第一个被触发的事件是 // when element is clicked it triggers the 'focus' event before the 'click' event
element.addEventListener( 'focus', ( e ) => {
e.stopImmediatePropagation(); // stops event propagation
// here goes the stuff you want to be executed once at a time
});
事件,该事件随后传播到
focus
事件。使用 Event.stopImmediatePropagation()我们中断传播,因此一次只会调用一个事件处理程序。 您体验到的双重输出来自
click
被
propagated从
event
事件到focus
事件处理程序。使用上述实现,您可以使用 click
或
click
事件,这无关紧要。