我过去遇到过类似的事情,并考虑了四种可能的方法:
- Using
$broadcast
- 将设置存储在
$rootScope
- 观察者模式(就像你在这里一样)
- Using
$watch
从控制器
以下是我对每个问题的想法:
$广播
在我看到的 AngularJS 演示中,Miško Hevery 谈到了使用$broadcast
(即事件)及其用例。要点是$broadcast
更适合对与您正在处理的任何内容不紧密相关的事件做出反应,否则可能会更好地选择替代方案。同样针对这个主题,最佳实践 https://github.com/angular/angular.js/wiki/Best-PracticesAngular wiki 上的指南建议:
仅对原子事件使用 .$broadcast()、.$emit() 和 .$on():活动
与整个应用程序全局相关(例如用户
身份验证或应用程序关闭)。
在这里,因为您的设置与填充的内容密切相关ng-view
,它会建议使用的替代方案$broadcast
是优选的。
$rootScope
正如您提到的(并且希望避免),这是一种全球状态。将设置公开给我的整个应用程序也不是/不是我个人的偏好,尽管它通常是一个简单的选择。我个人保留$rootScope
用于配置设置和“软”变量,例如页面标题等。我不会选择使用此选项。
观察者模式
针对配置工厂注册回调是一种可靠的方法。关于您的持久回调,您可以监听$destroy
作用域上的事件,调用remove
配置工厂上的方法来删除回调。这可以被认为是一个很好的例子$broadcast
使用;控制器关注该事件并且必须对其做出反应,但事件本身并不特定于控制器/配置服务共享的数据。
$watch
通过使用共享服务,可以将其注入到与设置相关的任何控制器中。现在,对配置的任何更改都会触发您的回调,而某些视图可能只涉及一两个配置设置。$watch
将使您能够更轻松地观察仅对这些属性的更改。我无法谈论开销与注册回调,但这对我来说感觉是最“有角度”的方式。
这就是如何使用它来实现$watch
:
var app = angular.module("myApp",[]);
app.factory("Configuration",function(){
var data = {
settingOne: true,
settingTwo: false
};
return data;
})
app.controller("SettingsCtrl",function($scope, Configuration){
// do something
})
app.controller("HomeCtrl",function($scope, Configuration){
// detect any change to configuration settings
$scope.$watch(function() {
return Configuration;
}, function(data) {
// do something
}, true)
// alternatively only react to settingTwo changing
$scope.$watch(function() {
return Configuration.settingTwo
}, function(data) {
// do something
})
})
请注意,如果您需要稍微复杂的配置工厂,您可以转而使用 getter/setter 方法并将配置设置本身保持私有。然后,在$watch
,您应该观察方法调用而不是属性本身。
UPDATE:
在回答时,我更喜欢采用$watch
在控制器内。使用框架开发一段时间后,我现在尝试保留$watch
完全脱离控制器,而是在可能的情况下更喜欢在值更改时直接调用函数,或者通过利用ng-change
.
这样做的原因之一是它增加了测试控制器的复杂性,但也许更重要的是它效率低下:对于每个$digest
循环角度调用,每个注册$watch
无论如何都会被评估,并且它很可能会响应对现有值所做的更改$watch
.
这里有一篇关于这个问题的非常好的文章,而不是从这个角度推测缺点和解决方案:Angular JS - 你可能不应该在控制器中使用 $watch http://www.benlesh.com/2013/10/title.html.