我尝试动态添加字段,并在指令的click
函数中绑定link
事件。但是当我添加更多字段时,似乎会多次触发。请参阅下面的示例 -
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);
};
});
&#13;
#content {
margin-top: 10px;
}
#clicks {
margin-top: 10px;
}
p {
color: grey;
}
&#13;
<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>
&#13;
我希望click
事件只针对特定元素触发一次。
答案 0 :(得分:2)
问题是因为你多次编译#content
DOM,因为你的旧元素再次被绑定点击事件到它。如果仔细观察,您会看到nth
按钮与n-1
点击事件绑定在一起。
以下是解释。
当您添加第一个按钮时,它会添加它并编译第一个按钮。
#content
有1个按钮,其中有1个点击事件绑定到它。当你添加第二个按钮时,它会被添加到DOM中,但它会重新编译整个#content
DOM,你知道它已经有了一个带有click事件的按钮。当您#content
DOM时,它将再次重新编译第一个指令,并再次向其添加click事件。它也会点击事件到第二个按钮。
#content
有2个按钮当您添加第3个按钮时,您将看到以下更改
#content
有2个按钮我说每次都不要通过重新编译DOM来自行渲染controls
。假设您已经添加了对页面进行第100次控制,因为您无缘无故地重新编译99
控件,从技术上讲这是没有意义的。因此,您应该将控制权交给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);
};
});
答案 1 :(得分:1)
你绑定@object.as_json({except: [:created_at, :updated_at]})
事件两次,
因为指令在链接阶段被初始化两次,其中click处理程序被绑定,你通过click
触发了摘要周期,它将事件附加到指令,因为它们处于链接阶段,但是事件可以绑定多次,因此指令有多个点击事件,首先建议是$compile(element.contents())(scope);
事件优先
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;
}
答案 2 :(得分:-1)
你需要以有棱角的方式思考。
只需像这样重写你的链接功能
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);
};