【问题标题】:AngularJS: How to handle keyboard shortcuts in routing controllers?AngularJS:如何处理路由控制器中的键盘快捷键?
【发布时间】:2016-03-28 16:16:47
【问题描述】:

如何在使用 routing 的 AngularJS 1.5 应用中实现页面特定的键盘快捷键

这就是我想要实现的目标:

index.html:

<!doctype html>
<html data-ng-app="myApp">
<body data-ng-keydown="onKeyDown($event)">
    ...
    <div data-ng-view></div>
    ...
</body>
</html>

据我了解,如果您在范围内没有聚焦的元素(例如输入字段,我没有),您需要处理 &amp;lt;body&amp;gt; 标记上的按键事件。

app.js:

var myApp = angular.module('myApp', ['ngRoute', 'myControllers']);

myApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'pages/home.html',
            controller: 'HomeCtrl'
        })
        .when('/create', {
            templateUrl: 'pages/create.html',
            controller: 'CreateCtrl'
        });
}]);

controllers.js:

var myControllers = angular.module('myControllers', []);

myControllers.controller('HomeCtrl', ['$scope', function ($scope) {

    $scope.closeLandingPagePopUp = function () {
        ...
    };

    $scope.onKeyDown = function ($event) {
        switch ($event.keyCode) {
            case 27: // [Esc]
                $scope.closeLandingPagePopUp();
                break;
            ...
        }
    };
}]);

myControllers.controller('CreateCtrl', ['$scope', function ($scope) {

    $scope.cancelCreation = function () {
        ...
    };

    $scope.onKeyDown = function ($event) {
        switch ($event.keyCode) {
            case 27: // [Esc]
                $scope.cancelCreation();
                break;
            ...
        }
    };
}]);

因此,在两个页面上,[Esc] 键的处理方式应该不同。

当然,HTML 属性 data-ng-keydown="onKeyDown($event)" 不起作用,因为它超出了控制器的范围。

有没有办法做到这一点,同时仍然将所有页面特定代码保留在各自的控制器中?

【问题讨论】:

  • 你应该使用小指令而不是控制器。

标签: javascript angularjs angularjs-directive angular-ui-router keyboard-shortcuts


【解决方案1】:

georgeawg's answer 很鼓舞人心,但我最终完成了这个实现:

myControllers.controller('HomeCtrl', ['$scope', '$document', function ($scope, $document) {

    var handleKeyDown = function(event) {
        switch (event.keyCode) {
            case 27: // [Esc]
                $scope.closeLandingPagePopUp();
                break;
            ...
        }
        $scope.$apply();
    };
    $document.on('keydown', handleKeyDown);

    $scope.$on('$destroy', function() {
        $document.unbind('keydown', handleKeyDown);
    });
}]);

在 HTML 部分中实际上没有什么可做的。

说明:

  1. 每个控制器都有一个实现快捷方式的handleKeyDown(event) 函数
  2. $document.on('keydown', handleKeyDown)在控制器初始化时将处理函数绑定到全局 keydown 事件。 $document 是 Angular 的 jQuery 包装器。
  3. 当控制器被销毁时解除绑定处理程序
  4. 使用 $scope.$apply() 让 Angular 知道数据何时发生变化以及视图需要刷新

【讨论】:

    【解决方案2】:

    全局按键指令

    要获取指令之外的事件,请将事件处理程序绑定到 $document

    angular.module('myApp').directive("globalKeydown", 
      function($document) {
        return function linkFn(scope,elem,attrs) {
            var handlerUnbind = $document.on("keydown", function(e) {
                scope.$eval(attrs.globalKeydown, {$event: e});
                scope.$apply();
            });
            scope.$on('$destroy', function() {
                 handlerUnbind();
            })
        }
    });
    

    此示例指令将keydown 事件处理程序放在调用global-event 属性定义的表达式的$document 上。事件曝光$event

    示例用法

    <div ng-app="myApp">
       <p>Click this window and press any key</p>
       <p global-keydown='keycode=($event.code)'>
          Global keydown = {{keycode}}
       </p>
    </div>
    

    DEMO on JSFiddle

    有关$event 的更多信息,请参阅AngularJS Developer Guide -- $event

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      • 2016-02-05
      • 1970-01-01
      • 2014-04-30
      • 1970-01-01
      • 2012-02-14
      • 2011-12-01
      相关资源
      最近更新 更多