在AngularJS中,根据当前视图上下文对Javascript事件应用操作

Apply actions on Javascript events depending on current view context in AngularJS

本文关键字:上下文 Javascript 事件 操作 应用 视图 AngularJS      更新时间:2023-09-26

我正在构建一个AngularJS SPA,它有多个元素,我想绑定按键事件。困难在于,由于Pinterest风格的模态窗口路由,几个元素,因此控制器范围,可以一次可见。这意味着某个按键事件将在多个控制器中触发,包括潜在的背景内容。

我想要绑定事件,或者至少只根据应用程序的当前状态/上下文对这些事件采取行动。有什么好的方法来处理这个问题吗?

我考虑过的:

  1. 使用Service来维护对状态的引用,并在全局级别上处理事件绑定,控制器可以根据其上下文订阅事件。但是我不知道如何在这个庄园里为Angular服务订阅函数。
  2. $routeChange事件上解除绑定和绑定事件,但感觉这会变得非常混乱。

我知道这是一个概念性的问题,但是我已经被困在这个问题上一段时间了,任何帮助都会非常感激。

我试图在这里做一个普朗克来证明这一点。每个上下文(应用程序的抽象状态)都有一个绑定到keypress事件的指令。我希望事件处理程序上的上下文在视图(即活动状态)是唯一一个执行。

我试图做一个简化但相关的例子。注意:

  • 大多数但不是所有的上下文/状态将有一个关联的路由,所以我不能仅仅依靠$stateChange事件
  • 许多状态是模态窗口,这意味着仍然可见的背景元素也可能正在监听按键。我不确定我能保证所有情况下的DOM顺序。
  • 我已经尝试使用元素focus,但这不起作用(想想tab out和back into应用程序,当这些元素涉及表单等问题)

希望这使它更清楚,我很高兴进一步更新。

在评论中进行了长时间的讨论(见上文)后,它归结为对服务的需求,该服务可以跟踪当前状态和按键,并在处于特定状态时接受按键的"订阅"。


下面是这样一个服务的通用实现,具有以下属性:
  1. 当前状态是外部设置的(你可以用任何你喜欢的方式实现它:ngRoute, uiRouter, $location change events或任何其他可能决定你的应用状态的东西)。

  2. 它公开了两个方法:一个用于设置状态,另一个用于订阅特定状态和keyCode的key-down事件。

  3. 订阅函数返回unsubscribe函数,可用于…你猜对了……退订!

  4. 这个演示实现假设在触发key-down事件时没有正在进行的$digest循环。如果您有不同的要求,您可以在调用$rootScope.$apply()之前检查。


app.factory('StateService', function ($document, $rootScope) {
    var currentState = 'init';
    var stateCallbacks = {};
    function fireKeydown(evt) {
        $rootScope.$apply(function () {
            ((stateCallbacks[currentState] || {})[evt.keyCode] || []).forEach(
                function (cb) {
                    cb(evt, currentState);
                }
            );
        });
    }
    function setState(newState) {
        currentState = newState;
    }
    function subscribeToKeydown(state, keyCode, callback) {
        if (!state || !keyCode || !callback) {
            return angular.noop;
        }
        stateCallbacks[state] = stateCallbacks[state] || {};
        stateCallbacks[state][keyCode] = stateCallbacks[state][keyCode] || [];
        stateCallbacks[state][keyCode].push(callback);
        function unsubscribe() {
            return ((stateCallbacks[state] || {})[keyCode] || []).some(
                function (cb, idx, arr) {
                    if (cb === callback) {
                        arr.splice(idx, 1);
                        console.log('Unsubscribed from state: ' + state);
                        return true;
                    }
                }
            );
        }
        console.log('Subscribed to state: ' + state);        
        return unsubscribe;
    }
    $document.on('keydown', fireKeydown);
    return {
        setState: setState,
        subscribeToKeydown: subscribeToKeydown
    };
});

这个<<p>看到,strong>短演示。