Javascript 角度:观察服务中的数据变化?
我的服务定义如下:Javascript 角度:观察服务中的数据变化?,javascript,angularjs,Javascript,Angularjs,我的服务定义如下: appServices.service('SharedData', function() { var data = {}; function setContacts(contacts) { data.contacts = contacts; }; function getContacts() { return data.contacts; }; return { setCon
appServices.service('SharedData', function() {
var data = {};
function setContacts(contacts) {
data.contacts = contacts;
};
function getContacts() {
return data.contacts;
};
return {
setContacts: setContacts,
getContacts: getContacts
};
});
在另一个控制器中,我访问数据如下:
$scope.contacts = SharedData.getContacts();
这一切都很好,但我希望当SharedData中的数据发生变化时,会提醒$scope.contacts
,并更新其数据
如何实现这一点?一种方法是在您的服务中定义一个函数,该函数允许您在调用
setContacts
时注册要调用的回调(onContactsUpdated
)。这个解决方案并不完美(例如,它只允许您注册一个“处理程序”),但应该让您走上正确的道路。如果需要在多个地方使用,可以对其进行调整
appServices.service('SharedData', function() {
var data = {};
function setContacts(contacts) {
data.contacts = contacts;
if(typeof(data.contactsUpdatedCallback) !== "undefined"){
data.contactsUpdatedCallback();
}
};
function getContacts() {
return data.contacts;
};
function onContactsUpdated(callback){
data.contactsUpdatedCallback = callback;
};
return {
setContacts: setContacts,
getContacts: getContacts,
onContactsUpdated: onContactsUpdated
};
});
然后在控制器中:
SharedData.onContactsUpdated(function(){
//do something with updated SharedData.getContacts()
});
尝试显式手表:
$scope.$watch(函数(){
返回SharedData.getContacts();
},功能(新联系人){
//对新联系人做些什么。
});代码>
如果集合的元素可以在整个集合对象不更改标识的情况下更改(我假设是数组
或对象
),则需要使用$scope.$watchCollection
,尽管这比普通的$watch
要慢得多,因此如果可以立即更改整个集合,请避免
请注意,将函数公开到只返回当前联系人的作用域可能是更好的设计:
$scope.getContacts=function(){return SharedData.getContacts();}代码>
如果您需要在SharedData
中发出通知,您可以将$rootScope
注入其中,并将$watch
放在上面。小心滥用它,但这正是$rootScope
用于:
appServices.service('SharedData', function($rootScope) {
var data = {};
function setContacts(contacts) {
data.contacts = contacts;
$rootScope.$broadcast('contacts-changed', contacts);
};
...
现在,在您想要的任何范围内,您都可以注册此事件:
function($scope) {
$scope.$on('contacts-changed', function(eventObj) {...});
}
您可以使用一个事件…并警告如果个人联系人已更新,则不会触发简单的手表。如果你也对此感兴趣,你需要使用$scope.$watchCollection
。@floribon我不喜欢这样使用$watch
——在每个摘要周期上运行这样的方法似乎是错误的。但是,按照服务的编写方式,一个简单的$watch
将起作用,因为每次使用setContacts
都会重置整个集合。我希望您会同意,$watchCollection
是一种非常痛苦的方式,因为它可能会在每个孩子身上迭代以寻找变化。美好的我对Angular很陌生,在不知道的情况下写下了我的答案。@MichaelHays我完全同意,并没有说你错了!我在jsut中添加了我的评论“作为警告”,以防OP希望单独更新联系人(在获得联系人后仍然可以)watchCollection
是否进行浅层对象属性监视:这一成本稍高,但与深度监视(使用$watch
并将最后一个参数设置为true)相比仍相差甚远,因此不应引起真正的关注。但我仍然同意你的观点,我个人也会采取倾听的方式。在发表我的评论之前,我向你投了赞成票:)哎呀,我想我最后回答的评论来自于答案海报(类似的名字)。我现在被说服了。无论如何,在评论之前,我把所有的答案都投了赞成票,因为它们都很好,所以不要被忽视。太棒了,谢谢。传入的varnv
有什么特别的含义吗?哈!你犯了个错误。我使用nv
来表示“新值”,但在本例中,它最好命名为evt
,并且是事件对象:这更有意义,谢谢。另一个问题:什么会被视为滥用这种技术?我最终会用它来广播十几个或更多的“已更改”事件。我的第一个想法是,“您的技术是否增加了代码的可读性?”我的第二个想法是,“如果它降低了代码的可读性,那么维护的增加是否抵消了合理的性能提高?”如果其中一个问题的答案是“否,”那么您可能滥用了该功能。除非你处于一个紧张的动画循环中,否则你的建议听起来不错。终于有机会回应了。问题#1:起初是的,但最终它变成了意大利面代码,很难理解。我学习了如何使用controllerAs(MainCtrl作为main
)语法,因为我的控制器是嵌套的,所以我可以轻松访问子控制器中的父模型(main.customer
)。它干净多了,不需要特别的广播。谢谢你帮助我保持谨慎!