今天我在使用$ watch的AngularJS中遇到了一些非常奇怪的行为。我将代码简化为以下示例:
https://jsfiddle.net/yLeLuard/
此示例包含一个跟踪state
变量的服务。指令用于将click事件绑定到DOM,通过服务更改state
变量。
此示例中存在两个问题:
main.html中
<div ng-controller="main">
State: {{ api.isOpen | json }}
<div ng-click="" open>
<button>Open - Working fine</button>
</div>
<div ng-click="" close>
<button>Close - Works, but only on second click</button>
</div>
<div open>
<button>Open - Not Working</button>
</div>
<div close>
<button>Close - Not Working</button>
</div>
</div>
main.js
var myApp = angular.module('myApp', []);
myApp.controller('main', ['$scope', 'state', function($scope, state) {
$scope.api = state;
$scope.api.isOpen = false;
$scope.$watch('api.isOpen', function() {
console.log('state has changed');
});
}]);
myApp.directive('open', ['state', function(state) {
return {
restrict: 'A',
scope: {},
replace: true,
template: '<button>Open</button>',
link: function(scope, element) {
element.on('click', function() {
state.isOpen = true;
});
}
};
}]);
myApp.directive('close', ['state', function(state) {
return {
restrict: 'A',
scope: {},
replace: true,
template: '<button>Close</button>',
link: function(scope, element) {
element.on('click', function() {
state.isOpen = false;
});
}
};
}]);
myApp.service('state', function() {
return {
isOpen: null
};
});
答案 0 :(得分:4)
那是因为您在click
上使用了本机事件监听器。此事件是异步的,不属于Angular摘要周期,因此您需要手动消化范围。
myApp.directive('open', ['state', function(state) {
return {
restrict: 'A',
scope: {},
link: function(scope, element) {
element.on('click', function() {
scope.$apply(function() {
state.isOpen = true;
});
});
}
};
}]);
修正小提琴:https://jsfiddle.net/7h95ct1y/
我建议直接在ng-click中更改状态:ng-click="api.isOpen = true"
答案 1 :(得分:0)
您应该将链接功能作为预链接功能,这解决了第二次点击的问题。
https://jsfiddle.net/2c9pv4xm/
myApp.directive('close', ['state', function(state) {
return {
restrict: 'A',
scope: {},
link:{
pre: function(scope, element) {
element.on('click', function() {
state.isOpen = false;
console.log('click', state);
});
}
}
};
}]);
对于不工作的部分,你将你的指令放在div上,所以当你单击div时它可以工作但不能按下按钮。你的开放指令应该在按钮上。
编辑:其他评论者建议您直接在ng-click中更改状态。我不推荐它,它可能适用于这种情况,但是如果你必须有更多的分配来做它不可行。