繁体   English   中英

AngularJS:动态绑定Click in指令被多次触发

[英]AngularJS: Dynamically binding Click in directive gets fired multiple times

我试图动态添加字段,并在指令的link函数中绑定click事件。 但是随着我添加更多字段,它似乎多次触发。 请参阅以下示例-

 var clicks = 0; var app = angular.module('test', []); app.directive('control', function($compile) { var linker = function(scope, element, attrs) { element.html('<button style="background:grey;">Button ' + scope.count + '</button>'); element.bind('click', function() { clicks++; $('#clicks').html('Clicked ' + clicks + ' times') }); $compile(element.contents())(scope); }; return { restrict: 'E', scope: { count: '@' }, link: linker } }); app.controller('TestController', function($scope, $compile) { $scope.count = 1; $scope.addControl = function() { $('#content').append('<control count="' + $scope.count+++'"></control>'); $compile($('#content').contents())($scope); }; }); 
 #content { margin-top: 10px; } #clicks { margin-top: 10px; } p { color: grey; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="test" ng-controller="TestController"> <button ng-click="addControl()">Add Button</button> <div id="content"></div> <div id="clicks"></div> </div> <p>Add multiple buttons and click the button that was added in the beginning. Notice the Clicks to be increased multiple times.</p> <p>For instance, add a bunch of buttons and click Button 1</p> 

我只想为特定元素触发一次click事件。

问题是因为您多次编译#content DOM,因此您的旧元素再次被绑定了click事件。 如果仔细观察,您会发现nth按钮绑定了n-1单击事件。

以下是说明。

  1. 当您添加第一个按钮时,确实会添加它并编译第一个按钮。

    • 现在,# #content具有1个按钮,该按钮已绑定1个click事件。
  2. 当您添加第二个按钮时,它会添加到DOM中,但会重新编译整个#content DOM,您知道它已经具有单击事件的1个按钮。 当您#content DOM时,它将再次重新编译第一个指令,并将再次向其添加click事件。 此外,它将单击事件到第二个按钮。

    • 现在#content有2个按钮
    • 第一个按钮绑定了2个事件
    • 第二个按钮有1个事件受其限制
  3. 当您添加第三个按钮时,您将看到以下更改

    • 现在#content有2个按钮
    • 第一个按钮绑定了3个事件
    • 第二个按钮有2个事件受其限制
    • 第三个按钮绑定了1个事件

我想说的是,不要每次都通过重新编译DOM自己在窗体上呈现controls 假设您已添加到页面的第100个控件,因为您无故重新编译了99控件,从技术上讲这没有意义。 因此,最好将ng-repeat呈现控件的责任ng-repeat

标记

<div ng-controller="TestController">
    <button ng-click="addControl()">Add Button</button>
    <div ng-repeat="control in controls"><control count="{{control}}"></control></div>
    <div id="clicks"></div>
</div>

调节器

app.controller('TestController', function($scope, $compile) {
  $scope.count = 1;
  $scope.controls = [];
  $scope.controlsCount = 0;
  $scope.addControl = function() {
    $scope.controls.push(++$scope.controlsCount);
  };
});

演示插件

您绑定了两次click事件, 在此处输入图片说明 因为伪指令在链接阶段绑定了点击处理程序,因此在链接阶段进行了两次初始化,所以您通过$compile(element.contents())(scope);触发了摘要循环$compile(element.contents())(scope); 将哪个事件附加到指令,因为它们处于链接阶段,但是事件可以绑定多次,因此指令具有多个click事件,首先建议先unbind事件

element.unbind('click').bind('click');

您可能会问,元素可能具有多个点击事件是怎么回事,这就是

//event1
document.body.onclick = function(){ console.log('event1'); }

//event2
var oldClick = document.body.onclick;
document.body.onclick = function(){ console.log('event2'); oldClick.bind(document.body).call(); }

//this will trigger
event2
event1

在此处输入图片说明

下面的工作样本

 var clicks = 0; var app = angular.module('test', []); app.directive('control', function($compile) { var linker = function(scope, element, attrs) { element.html('<button style="background:grey;">Button ' + scope.count + '</button>'); element.unbind('click').bind('click', function() { clicks++; $('#clicks').html('Clicked ' + clicks + ' times') }); $compile(element.contents())(scope); }; return { restrict: 'E', scope: { count: '@' }, link: linker } }); app.controller('TestController', function($scope, $compile) { $scope.count = 1; $scope.addControl = function() { $('#content').append('<control count="' + $scope.count+++'"></control>'); $compile($('#content').contents())($scope); }; }); 
 #content { margin-top: 10px; } #clicks { margin-top: 10px; } p { color: grey; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="test" ng-controller="TestController"> <button ng-click="addControl()">Add Button</button> <div id="content"></div> <div id="clicks"></div> </div> <p>Add multiple buttons and click the button that was added in the beginning. Notice the Clicks to be increased multiple times.</p> <p>For instance, add a bunch of buttons and click Button 1</p> 

您需要以有角度的方式思考。

只是这样重写链接功能

var linker = function(scope, element, attrs) {
 element.html('<button ng-click="onClick()"  style="background:grey;">Button ' + scope.count + ' Clicked {{clicks}} times</button>');

 scope.clicks=0;
 scope.onClick = function(){
  scope.clicks+;
 }
 $compile(element.contents())(scope);
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM