这就是我目前所拥有的:
http://plnkr.co/edit/L9XqEyOtRSGHc9rqFPJX
我试图这样做,以便当我第一次按下向下键时,焦点将转移到#div2
;重复动作应该将焦点移到li > div:first-child
。
然而,在演示中,第一次按下向下键时,焦点将直接跳至li > div:first-child
,因为key-map
上的#div1
和#div2
捕获了相同的keydown事件,因此焦点一次从#div1
跳到#div2
,然后从#div2
跳到li > div:first-child
。
我应该如何解决这个问题,或者更好的是,无论如何都要改进代码的结构?我不确定这些事件监听器是否正在以最佳方式附加到DOM。
答案 0 :(得分:2)
您正在为每个元素的文档附加keydown
处理程序。我认为stopPropagation()
不会有任何好处,因为两个处理程序位于同一个元素上,它不会从文档传播,但两者仍然会触发。
我建议重新评估你是如何接近它的。你只希望带有焦点类的元素对它的选项进行评估,那么为什么不用你的指令将所有这些元素包装在一个元素中,让它只听一次并选择要处理的元素。
<div key-mapped="">
<!-- children will apply key map of element with focus class -->
<div id="div1" class="focus" key-map="{
40: '#div2'
}">Hello</div>
指令:
}).directive('keyMapped', function($rootScope) {
return {
restrict: 'A',
link: function(scope, element, attr) {
angular.element(document).bind('keydown', function(event) {
var target = $(element).find('.focus');
console.log('target: ' + target);
var options = scope.$eval(target.attr('key-map'));
的 ---- ---- EDIT 强> 的
有人告诉我这是不是一个好的做法,但是你总是可以把事件处理程序放在你的指令对象上,并确保它只设置一次并将自定义事件发送到你绑定的'focus'类的元素在你的链接功能。
}).directive('keyMap', function($rootScope) {
var dir = {
onKeydown: function(event) {
var element = document.querySelector('.focus');
var newEvent = new CustomEvent("keyMapKeydown", {
detail: { keyCode: event.keyCode },
bubbles: false,
cancelable: true
});
element.dispatchEvent(newEvent);
},
registered: false, // ensure we only listen to keydown once
restrict: 'A',
link: function(scope, element, attr) {
// register listener only if not already registered
if (!dir.registered) {
dir.registered = true;
angular.element(document).bind('keydown', dir.onKeydown);
}
var options = scope.$eval(attr.keyMap);
// listen for custom event which will be dispatched only to the
// element that has the 'focus' class
element.bind('keyMapKeydown', function(event) {
var keyCode = event.detail.keyCode;
if (options && (keyCode in options)) {
element.removeClass('focus');
angular.element(document.querySelector(options[keyCode])).addClass('focus');
event.stopPropagation();
}
});
}
};
答案 1 :(得分:0)
您需要停止事件的传播。事件向上传播。在你的指令中添加如下内容:
$(elm).click(function (event) {
event.stopPropagation();
});
或者,您可以自己创建一个停止传播指令。 This SO question有很好的方法。