3

我在 Angular 中遇到了一种情况,我感觉自己做错了,但我找不到 Angular 的方法来解决它。

我正在开发一个移动应用程序。我想创建一个指令,让我们称之为cc-tap-highlight将与 ng-click 一起使用的指令。这意味着我可以像这样使用它:

<a ng-click="doSomething()" cc-tap-highlight>Click me</a>

这将做的是向单击的元素添加一个类,并在几秒钟后将其删除。

现在可以说,让我们手动绑定到click指令中的元素事件。这适用于桌面应用程序。然而,在移动设备Angular上,我们可以快速点击/点击很多魔法:

https://github.com/angular/angular.js/blob/master/src/ngMobile/directive/ngClick.js

当然,我不想重新实现它的所有魔法!

所以,目前,我没有使用我的cc-tap-highlight指令,而是使用这种相当老套的方法:

在视图中

<a ng-click="doSomething($event)" cc-tap-highlight>Click me</a>

在控制器中:

$scope.doSomething = function($event){
    //do your things with $event.currentTarget
}

这种方法有两个主要问题:

  1. 控制器不应操纵 DOM

  2. 我们需要在整个违反 DRY 的代码库中一遍又一遍地重复这种模式

但是,我一生都无法弄清楚如何编写一个挂钩到ng-click处理程序并完成它的事情的指令。

4

1 回答 1

2

你可以尝试让你的指令生成一个带有包装函数的 ng-click 指令。

这是一个简单的例子。到目前为止,它还没有经过彻底的测试,但我认为这个原则是合理的。您想要的是您的自定义代码在点击事件之前/之后运行,而不管它是如何触发的(点击、点击等)。

这确实有一个缺点,它创建了一个新的范围,因此没有测试与可能需要隔离范围的其他指令的交互。

指示

app.directive('myClick', ['$parse','$compile', function($parse, $compile) {
  return {
    restrict: 'A',
    compile : function(tElement, tAttrs, transclude) {
      //you can call the wrapper function whatever you want.
      //_myClick might be more appropriate to indicate it's not really public
      tElement.attr('ng-click', 'myClick($event)');
      tElement.removeAttr('my-click');
      var fn = $parse(tAttrs['myClick']);

      return {
        pre : function(scope, iElement, iAttrs, controller) {
          console.log(scope, controller);
          scope.myClick = function(event) {
            console.log('myClick.before');
            fn(scope, {$event:event});
            console.log('myClick.after');
          };

          $compile(iElement)(scope);
        },
        post : function postLink(scope, iElement, iAttrs, controller) {

        }
      };
    },
    scope : true
  };
}]);

控制器

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';

  $scope.test = function($event) {
    console.log('test', $event);
  };

  //this is to show that even if you have a function with the same name,
  //the wrapper function is still the one bound thanks to the new scope
  $scope.myClick = function() {
    console.log('dummy my click');
  };
});

HTML

<button ng-click="test($event)">NG-CLICK</button>
<button my-click="test($event)">MY-CLICK</button>
<button ng-click="myClick($event)">MY-CLICK-DUPLICATE-FN</button>
于 2013-07-12T23:50:41.350 回答