[英]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
单击事件。
以下是说明。
当您添加第一个按钮时,确实会添加它并编译第一个按钮。
#content
具有1个按钮,该按钮已绑定1个click事件。 当您添加第二个按钮时,它会添加到DOM中,但会重新编译整个#content
DOM,您知道它已经具有单击事件的1个按钮。 当您#content
DOM时,它将再次重新编译第一个指令,并将再次向其添加click事件。 此外,它将单击事件到第二个按钮。
#content
有2个按钮 当您添加第三个按钮时,您将看到以下更改
#content
有2个按钮 我想说的是,不要每次都通过重新编译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.