如何在使用ng-click时自动传递$event参数?

74

我知道如果像这样传递 $event 对象,就可以从 ng-click 中获取单击事件:

<button ng-click="myFunction($event)">Give me the $event</button>

<script>
  function myFunction (event) {
    typeof event !== "undefined" // true
  }
</script>

每次都要明确地传递$event有点烦人。是否可以将ng-click设置为默认情况下将其传递给函数?


11
我知道这段代码只是为了演示,但 undefined 应该改为 "undefined",否则由于 typeof 返回的是一个字符串,表达式将总是被判定为假。 - Fabrício Matté
1
我在想为什么你需要$event - a better oliver
6
Event对象通常用于停止事件冒泡/传播。 - Stewie
3
myFunction 是控制器的一部分。控制器不应该关心用户界面(UI)。此外,一个简单的按钮没有默认操作。而且Angular可以预防很多默认操作。虽然你是正确的,但很难想象有一个好的使用场景。 - a better oliver
1
@zeroflagL,我有一个指令contextMenu,它为作用域提供了几个函数(打开、关闭、切换),这些函数是通过特定的contextMenu名称调用的,例如ng-click="account_menu.toggle()"。菜单本身位于不同的元素中,例如<div context-menu="account_menu"></div>"。为了在页面上正确地定位菜单,使其位于调用toggle()的触发元素正下方,我想访问ng-click$event.target元素,以便获取其坐标。如果有更简单的方法,请告诉我 :) - Elise
显示剩余8条评论
4个回答

65

看一眼 ng-click 指令的源代码:

...
compile: function($element, attr) {
  var fn = $parse(attr[directiveName]);
  return function(scope, element, attr) {
    element.on(lowercase(name), function(event) {
      scope.$apply(function() {
        fn(scope, {$event:event});
      });
    });
  };
}

它展示了如何将event对象通过使用$event作为参数名称传递给ng-click表达式。这是由$parse服务完成的,该服务不允许参数进入目标作用域,这意味着答案是否定的,除了通过回调参数以外,不能以任何其他方式访问$event对象。


46

$event添加到ng-click中,例如:

<button type="button" ng-click="saveOffer($event)" accesskey="S"></button>

然后 jQuery.Event 被传递到回调函数中:

在此输入图片描述


19
除了这正是 OP 所试图避免的事情,除非我疯了。整篇文章的重点是在不显式传递 $event 的情况下访问它... 而这似乎正是你在这里做的事情。 - dudewad
3
我可以接受它。 - svarog
7
在谷歌搜索如何通过$event后,最终来到了这里。与其他点赞者类似,没有阅读原始问题 :-| - RasikaSam

11

就像其他人所说,你实际上无法严格地做到你所要求的。 话虽如此,Angular框架可用的所有工具也同样适用于您! 这意味着您实际上可以编写自己的元素并自己提供此功能。 我编写了一个示例,您可以在以下plunkr中查看(http://plnkr.co/edit/Qrz9zFjc7Ud6KQoNMEI1)。

关键部分是我定义了一个“可单击”元素(如果需要支持旧版IE,请勿这样做)。 在代码中看起来像:

<clickable>
  <h1>Hello World!</h1>
</clickable>

然后我定义了一个指令来将这个可点击的元素转换为我想要的东西(自动设置我的点击事件):

app.directive('clickable', function() {
    return {
        transclude: true,
        restrict: 'E',
        template: '<div ng-transclude ng-click="handleClick($event)"></div>'
    };
});

最后在我的控制器中,我已经准备好了点击事件:

$scope.handleClick = function($event) {
    var i = 0;
};

现在,值得一提的是,这个代码硬编码了处理点击事件的方法名称。如果你想要消除这种情况,你应该能够向指令提供你自己的点击处理程序的名称,然后“tada”——你就有一个可以使用且不必再注入“$event”的元素(或属性)。

希望这可以帮助你!


1
你需要将handleClick事件变成可传递的东西,伙计 :) - vbullinger

2
我建议不要这样做,但你可以覆盖ngClick指令以实现你想要的功能。这并不意味着你应该这样做。
考虑到原始实现:
compile: function($element, attr) {
  var fn = $parse(attr[directiveName]);
  return function(scope, element, attr) {
    element.on(lowercase(name), function(event) {
      scope.$apply(function() {
        fn(scope, {$event:event});
      });
    });
  };
}

我们可以这样覆盖它:
// Go into your config block and inject $provide.
app.config(function ($provide) {

  // Decorate the ngClick directive.
  $provide.decorator('ngClickDirective', function ($delegate) {

    // Grab the actual directive from the returned $delegate array.
    var directive = $delegate[0];

    // Stow away the original compile function of the ngClick directive.
    var origCompile = directive.compile;

    // Overwrite the original compile function.
    directive.compile = function (el, attrs) {

      // Apply the original compile function. 
      origCompile.apply(this, arguments);

      // Return a new link function with our custom behaviour.
      return function (scope, el, attrs) {

        // Get the name of the passed in function. 
        var fn = attrs.ngClick;

        el.on('click', function (event) {
          scope.$apply(function () {

            // If no property on scope matches the passed in fn, return. 
            if (!scope[fn]) {
              return;
            }

            // Throw an error if we misused the new ngClick directive.
            if (typeof scope[fn] !== 'function') {
              throw new Error('Property ' + fn + ' is not a function on ' + scope);
            }

            // Call the passed in function with the event.
            scope[fn].call(null, event);

          });
        });          
      };
    };    

    return $delegate;
  });
});

然后您可以像这样传递您的函数:
<div ng-click="func"></div>

相对于:
<div ng-click="func()"></div>

jsBin: http://jsbin.com/piwafeke/3/edit

正如我所说的,我不建议这样做,但这是一个概念证明,向您展示,是的-您确实可以覆盖/扩展/增强内置的angular行为以适应您的需求。而不必深入原始实现。

如果您决定走这条路(虽然很有趣),请小心使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接