0

这是我目前拥有的:

http://plnkr.co/edit/L9XqEyOtRSGHc9rqFPJX

我正在努力做到这一点,以便当我第一次按下向下键时,焦点将移至#div2; 重复动作应该让焦点移到li > div:first-child.

然而在demo中,第一次按下down键时,焦点会li > div:first-child直接跳转到,因为key-mapon#div1#div2捕获的keydown事件是一样的,所以焦点从跳转#div1#div2then#div2li > div:first-child一次。

我应该如何解决这个问题,或者更好的是,是否有办法改进代码的结构?我不确定这些事件侦听器现在是否以最佳方式附加到 DOM。

4

2 回答 2

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'));

- - 编辑 - -

有人让我知道这是否不是一个好习惯,但是您始终可以将事件处理程序放在指令对象上,并确保它只设置一次,并将自定义事件发送到您绑定到您的“焦点”类的元素链接功能。

(笨蛋)

}).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();
        }
      });
    }
  };
于 2013-07-03T05:22:49.037 回答
0

您需要停止事件的传播。事件向上传播。在您的指令中输入如下内容:

$(elm).click(function (event) {                
    event.stopPropagation();
});

或者,您可以自己创建一个停止传播指令。这个 SO question有一个很好的方法。

于 2013-07-03T05:04:00.883 回答