有条件地剥离其他指令的指令

directive to conditionally strip other directives

我正在尝试创建一个指令,该指令将通过以下三种方式之一影响目标元素:1. 保留它,2. 在编译之前删除所有其他指令,以便用户无法与其交互(ng-click,例如), 3. 完全删除元素。

到目前为止,我可以让所有三个都起作用,但只能在 select 个元素上起作用。我有一个可点击的跨度,如果我应用选项 2,它就可以正常工作。 ng-click 被剥离,用户无法交互;然而,将相同的逻辑应用于按钮元素会导致奇怪的副作用。首先,它没有删除 ng-click,而是复制了事件侦听器。经过检查,该元素没有附加两个 ng-click 指令,但它确实有两个点击监听器,点击它会导致相同的动作发生两次。

下面是当前指令和我正在使用的当前模拟模型。

return {
  restrict: 'A',
  priority: 1500,
  compile(elem, attr) {
    let action = () => { /**/ };

    const currentLocation = $location.path().split('/')[1];
    const permissionsLocation = appConfig[currentLocation];
    const fullPath = attr.permissions;
    if (_.has(permissionsLocation, fullPath)) {
      const permLevel = _.get(permissionsLocation, fullPath);
      if (permLevel === 'disable') {
        action = (scope, element) => {
          attr.$set('disabled');
          elem.css({
            cursor: 'not-allowed'
            // 'pointer-events': 'none'
          });
          elem
            .addClass('no-permissions')
            .removeAttr('ng-click')
            .removeAttr('ng-keyup')
            .removeAttr('ng-change')
            .removeAttr('ng-touchstart')
            .removeAttr('ng-touchend')
            .removeAttr('permissions');
          $compile(element)(scope);
        };
      } else if (permLevel === 'destroy') {
        action = (scope, element) => {
          element.remove();
        };
      }
    }
    return {
      pre(scope, element) {
        action(scope, element);
      }
    };
  }
};

型号:

appConfig.location1 = {
      thing1: {
        perm1: 'disable',
        perm2: 'destroy',
        perm3: 'destroy'
      },
      thing2: {
        perm4: 'disable'
      }
    };

这就是我应用指令的方式:

<button ng-click="blah()" permissions="thing1.perm1"></button>

通过纯粹的实验,我发现使用 post 方法而不是 pre 并在删除属性后立即调用 elem.off() 解决了我的问题并从中删除了所有事件侦听器我希望禁用的元素。只做一个或另一个会导致相同的错误。

如果有人可以解释这种行为并且可能对我正在做的事情提出更好的解决方案,我会接受这个答案。