Javascript AngularJS创建全局键盘快捷键的方法是什么?
我想我应该使用指令,但将指令添加到正文中,但侦听文档上的事件似乎很奇怪 这样做的正确方法是什么Javascript AngularJS创建全局键盘快捷键的方法是什么?,javascript,angularjs,Javascript,Angularjs,我想我应该使用指令,但将指令添加到正文中,但侦听文档上的事件似乎很奇怪 这样做的正确方法是什么 更新:找到AngularJS UI并看到了keypress指令的实现。以下是我如何使用jQuery实现的-我认为有更好的方法 var app = angular.module('angularjs-starter', []); app.directive('shortcut', function() { return { restrict: 'E', replace: true,
更新:找到AngularJS UI并看到了keypress指令的实现。以下是我如何使用jQuery实现的-我认为有更好的方法
var app = angular.module('angularjs-starter', []);
app.directive('shortcut', function() {
return {
restrict: 'E',
replace: true,
scope: true,
link: function postLink(scope, iElement, iAttrs){
jQuery(document).on('keypress', function(e){
scope.$apply(scope.keyPressed(e));
});
}
};
});
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.keyCode = "";
$scope.keyPressed = function(e) {
$scope.keyCode = e.which;
};
});
按查看键
{{keyCode}}
使用
$document.bind
:
function FooCtrl($scope, $document) {
...
$document.bind("keypress", function(event) {
console.debug(event)
});
...
}
我想说一种更合适的方式(或“角度方式”)是将其添加到指令中。下面是一个简单的方法(只需将
keypress events
属性添加到
):
在您的指令中,您可以简单地执行以下操作:
module.directive('myDirective', [
function() {
return {
restrict: 'E',
link: function(scope, el, attrs) {
scope.keyPressed = 'no press :(';
// For listening to a keypress event with a specific code
scope.$on('keypress:13', function(onEvent, keypressEvent) {
scope.keyPressed = 'Enter';
});
// For listening to all keypress events
scope.$on('keypress', function(onEvent, keypressEvent) {
if (keypress.which === 120) {
scope.keyPressed = 'x';
}
else {
scope.keyPressed = 'Keycode: ' + keypressEvent.which;
}
});
},
template: '<h1>{{keyPressed}}</h1>'
};
}
]);
function MyController($scope, $timeout, keyboardManager) {
// Bind ctrl+shift+d
keyboardManager.bind('ctrl+shift+d', function() {
console.log('Callback ctrl+shift+d');
});
}
module.directive('myDirective'[
函数(){
返回{
限制:'E',
链接:功能(范围、el、属性){
scope.keyPressed='不按:(';
//用于收听带有特定代码的按键事件
作用域:$on('keypress:13',功能(OneEvent,keypressEvent){
scope.keyPressed='Enter';
});
//用于收听所有按键事件
作用域:$on('keypress',功能(OneEvent,keypressEvent){
if(按键,哪个===120){
scope.keyPressed='x';
}
否则{
scope.keyPressed='Keycode:'+keypressEvent.which;
}
});
},
模板:“{keyPressed}}”
};
}
]);
以下是键盘快捷键AngularJS服务的示例:
然后可以这样使用它:
module.directive('myDirective', [
function() {
return {
restrict: 'E',
link: function(scope, el, attrs) {
scope.keyPressed = 'no press :(';
// For listening to a keypress event with a specific code
scope.$on('keypress:13', function(onEvent, keypressEvent) {
scope.keyPressed = 'Enter';
});
// For listening to all keypress events
scope.$on('keypress', function(onEvent, keypressEvent) {
if (keypress.which === 120) {
scope.keyPressed = 'x';
}
else {
scope.keyPressed = 'Keycode: ' + keypressEvent.which;
}
});
},
template: '<h1>{{keyPressed}}</h1>'
};
}
]);
function MyController($scope, $timeout, keyboardManager) {
// Bind ctrl+shift+d
keyboardManager.bind('ctrl+shift+d', function() {
console.log('Callback ctrl+shift+d');
});
}
更新:我现在改用。我为快捷方式提供了服务 它看起来像:
angular.module('myApp.services.shortcuts', [])
.factory('Shortcuts', function($rootScope) {
var service = {};
service.trigger = function(keycode, items, element) {
// write the shortcuts logic here...
}
return service;
})
我把它注入控制器:
angular.module('myApp.controllers.mainCtrl', [])
.controller('mainCtrl', function($scope, $element, $document, Shortcuts) {
// whatever blah blah
$document.on('keydown', function(){
// skip if it focused in input tag
if(event.target.tagName !== "INPUT") {
Shortcuts.trigger(event.which, $scope.items, $element);
}
})
})
hotkeys.add('n', 'Create a new Category', $scope.showCreateView);
hotkeys.add('e', 'Edit the selected Category', $scope.showEditView);
hotkeys.add('d', 'Delete the selected Category', $scope.remove);
它可以工作,但您可能会注意到我将$element和$document注入控制器
这是一种糟糕的控制器实践,违反了“永远不要访问控制器中的$element”约定
我应该把它放到指令中,然后使用'ngKeydown'和$event来触发服务
但我认为服务很好,我会尽快重做控制器
更新: 似乎“ng keydown”只在输入标记中起作用 因此,我只需编写一个指令并注入$document:
angular.module('myApp.controllers.mainCtrl', [])
.directive('keyboard', function($scope, $document, Shortcuts) {
// whatever blah blah
return {
link: function(scope, element, attrs) {
scope.items = ....;// something not important
$document.on('keydown', function(){
// skip if it focused in input tag
if(event.target.tagName !== "INPUT") {
Shortcuts.trigger(event.which, scope.items, element);
}
})
}
}
})
更好。我现在还不能保证,但我已经开始查看AngularHotkeys.js: 一旦我下定决心,我会更新更多信息 更新1:哦,有一个nuget软件包:角度热键 更新2:实际上非常容易使用,只需在路线中或在控制器中设置绑定:
angular.module('myApp.controllers.mainCtrl', [])
.controller('mainCtrl', function($scope, $element, $document, Shortcuts) {
// whatever blah blah
$document.on('keydown', function(){
// skip if it focused in input tag
if(event.target.tagName !== "INPUT") {
Shortcuts.trigger(event.which, $scope.items, $element);
}
})
})
hotkeys.add('n', 'Create a new Category', $scope.showCreateView);
hotkeys.add('e', 'Edit the selected Category', $scope.showEditView);
hotkeys.add('d', 'Delete the selected Category', $scope.remove);
略短一点的答案是看下面的解决方案3。如果你想知道更多选项,你可以阅读全文 我同意jmagnusson。但我相信有更干净的解决方案。与其在指令中绑定键和函数,不如像定义配置文件一样在html中绑定它们,热键应该是上下文的
<div ng-app="keyExample">
<div ng-controller="RootController">
<keybinding on="g i" invoke="gotoInbox()" />
<div ng-controller="ChildController">
<keybinding on="g l" invoke="gotoLabel('Sent')" />
</div>
</div>
<div>Click in here to gain focus and then try the following key strokes</div>
<ul>
<li>"g i" to show a "Goto Inbox" alert</li>
<li>"g l" to show a "Goto Label" alert</li>
</ul>
</div>
在使用了所有的解决方案之后,我推荐Angular UI团队实现的解决方案,解决方案3避免了我遇到的许多奇怪的小问题。从guys behid ng-newsletter.com查看这一点;查看创建2048游戏,它有一些很好的代码,使用键盘事件服务。作为指示
.directive('shortcuts', ['$document', '$rootScope', function($document, $rootScope) {
$rootScope.shortcuts = [];
$document.on('keydown', function(e) {
// Skip if it focused in input tag.
if (event.target.tagName !== "INPUT") {
$rootScope.shortcuts.forEach(function(eventHandler) {
// Skip if it focused in input tag.
if (event.target.tagName !== 'INPUT' && eventHandler)
eventHandler(e.originalEvent, e)
});
}
})
return {
restrict: 'A',
scope: {
'shortcuts': '&'
},
link: function(scope, element, attrs) {
$rootScope.shortcuts.push(scope.shortcuts());
}
};
}])
这基本上是在Angular documentation代码中完成的,即按/
开始搜索
angular
.module("app", [])
.directive("keyboard", keyboard);
function keyboard($document) {
return {
link: function(scope, element, attrs) {
$document.on("keydown", function(event) {
// if keycode...
event.stopPropagation();
event.preventDefault();
scope.$apply(function() {
// update scope...
});
}
};
}
使用键盘指令的Plunk
作为一项服务
.directive('shortcuts', ['$document', '$rootScope', function($document, $rootScope) {
$rootScope.shortcuts = [];
$document.on('keydown', function(e) {
// Skip if it focused in input tag.
if (event.target.tagName !== "INPUT") {
$rootScope.shortcuts.forEach(function(eventHandler) {
// Skip if it focused in input tag.
if (event.target.tagName !== 'INPUT' && eventHandler)
eventHandler(e.originalEvent, e)
});
}
})
return {
restrict: 'A',
scope: {
'shortcuts': '&'
},
link: function(scope, element, attrs) {
$rootScope.shortcuts.push(scope.shortcuts());
}
};
}])
将该指令转换为服务非常容易。唯一真正的区别是作用域未在服务上公开。要触发摘要,可以引入$rootScope
或使用$timeout
function Keyboard($document, $timeout, keyCodes) {
var _this = this;
this.keyHandlers = {};
$document.on("keydown", function(event) {
var keyDown = _this.keyHandlers[event.keyCode];
if (keyDown) {
event.preventDefault();
$timeout(function() {
keyDown.callback();
});
}
});
this.on = function(keyName, callback) {
var keyCode = keyCodes[keyName];
this.keyHandlers[keyCode] = { callback: callback };
return this;
};
}
现在,您可以使用keyboard.on()
方法在控制器中注册回调
function MainController(keyboard) {
keyboard
.on("ENTER", function() { // do something... })
.on("DELETE", function() { // do something... })
.on("SHIFT", function() { // do something... })
.on("INSERT", function() { // do something... });
}
使用服务的Plunk的替代版本
下面让我们将所有快捷方式逻辑写入控制器,指令将处理所有其他内容 指令
.directive('shortcuts', ['$document', '$rootScope', function($document, $rootScope) {
$rootScope.shortcuts = [];
$document.on('keydown', function(e) {
// Skip if it focused in input tag.
if (event.target.tagName !== "INPUT") {
$rootScope.shortcuts.forEach(function(eventHandler) {
// Skip if it focused in input tag.
if (event.target.tagName !== 'INPUT' && eventHandler)
eventHandler(e.originalEvent, e)
});
}
})
return {
restrict: 'A',
scope: {
'shortcuts': '&'
},
link: function(scope, element, attrs) {
$rootScope.shortcuts.push(scope.shortcuts());
}
};
}])
控制器
$scope.keyUp = function(key) {
// H.
if (72 == key.keyCode)
$scope.toggleHelp();
};
Html
<div shortcuts="keyUp">
<!-- Stuff -->
</div>
你可以试试这个库。它使管理热键变得非常容易,在你浏览应用程序时,它会自动绑定和解除绑定键
我不知道这是否是一种真正的角度方式,但我做了什么
$(document).on('keydown', function(e) {
$('.button[data-key=' + String.fromCharCode(e.which) + ']').click();
});
<div class="button" data-key="1" ng-click="clickHandler($event)">
ButtonLabel
</div>
$(文档).on('keydown',函数(e){
$('.button[data key='+String.fromCharCode(e.which)+']')。单击();
});
纽扣标签
我想你指的是键盘快捷键……我对此也很好奇,我得出的结论是angular并不是执行此任务的最佳工具。我写了一个指令来实现这一点,但存在一些问题——首先是你提到的语义问题,而且我认为在指令中封装jquery被认为不是一个好的做法,当有多个模板时,这导致了一些混乱的情况,其中只有一些模板需要文档快捷方式。快捷方式需要与我的控制器连接。我看不到外部jquery模块的任何好处。我也看到了两种可能的方式:1)jquery外部快捷方式模块+与控制器的pubsub通信。2) angularjs指令,这很奇怪,但我认为提供带有快捷方式的链接函数是可以的。我不认为您可以将angularjs ui指令添加到文档中,它们的作用域是一个元素。不需要额外的库。。。使用$document.bind('keypress')
查看链接现在是404。如果有更新的位置,请更新。谢谢回复。我知道你认为我们应该按照指令来做。link:functionpostlink(scope,iElement,iAttrs){wi