任何人都可以就使用事件的优缺点给我一些建议,以保持Angular应用程序的不同部分彼此同步吗?
我正在考虑使用一系列事件和事件监听器将SPA与多个并发和嵌套视图连接在一起,由Angular ui-router提供。 SPA的布局可以类似于gmail,其中屏幕上有逻辑上独立的区域(左侧区域包含邮件文件夹列表,顶部导航栏,主要详细信息视图等)。
我一直在研究如何让所有控制器与他们都需要同时访问的模型保持同步。当顶视图更新模型时,如果某个模型显示在主视图中,我希望主视图注意到更改,并相应地更新其视图。
我使用服务来跨控制器共享模型,这被认为是最佳实践,但深度in this question中讨论的方法存在问题。
可能的解决方案是使用Angular的$broadcast
和.$on('event, fn())
让控制器在他们关心的服务更新数据时发出通知。
问题:
表现(整个$范围层次结构中的事件泡沫等)。
$broadcast
/ $emit
有一些性能和紧密耦合的问题,这些问题在本地和其他地方都有很多内容,我正在考虑使用SO回答here中的解决方案来解决性能问题/当控制器被破坏时,内存泄漏而不清理侦听器。
维护(意大利面条代码/忽略OO,只是在事件中传递整个应用程序的模型)。
这是我对社区的主要问题:基于下面的(丑陋)图表,我想象每个角度.service
在获得更新模型数据时触发事件,并且任何关心该数据的控制器只是监听要发射的事件:
编码实际上很简单(现在可以使用),但是我担心从现在起5年来一直试图跟踪所有事件关系。
有没有人对这样的设计有过任何经验,谁可以就更智能/更简洁的设计给我一些建议?
提前致谢,对原始图表感到抱歉......希望它可以解决问题。
答案 0 :(得分:2)
赞成?
缺点?
我已经回答了您链接的其中一个问题:here这样可能会对您有所帮助。
您可能也会在评论中回答这个问题。
我的建议是不要放弃OO。但是拥抱它,棱角分明会通过一直工作来奖励你。
如果您处于一个普遍链接的问题中,如果User
对象带有密码字段,您将永远不会遇到问题因为密码始终可以通过用户进行引用。并且User.password
的所有绑定都会起作用。
所以只有一个数据源。保留该参考。您的双向绑定将修改该数据。您不必担心在事件中将其传播到整个应用程序中。
答案 1 :(得分:2)
因为这太长了,要把它写成评论回复,我将其贴出来作为答案:
如果要验证用户输入并保持服务中的状态(或其共享部分或域模型),我会将表单的viewmodel仅放在控制器中并调用服务方法来更新模型。此方法将返回一组验证错误:
$scope.errors = myModel.update($scope.formFields);
或者在这种情况下,用户必须单击按钮才能提交表单:
$scope.$watch('formFields', function (values) {
$scope.errors = myModel.validate(values);
});
$scope.submit = function () {
$scope.errors = myModel.update($scope.formFields);
if ($scope.errors.length < 0) {
$scope.formFields = {};
$scope.showForm = false;
}
};
为避免直接访问域模型,您可以在服务中保留此数据,并仅提供访问数据的方法。
服务:
var items = {};
return {
'getItems': function () {
return items;
}
};
在控制器中:
$scope.myList = myListModelService;
在视图中:
<li ng-repeat="item in myList.getItems()">
当然,这允许开发人员直接修改返回的对象/数组($scope.myList.getItems().push(newItem);
)。在这里你必须决定,要么声明一个约定:“永远不要直接更新模型对象;永远使用模型服务的API”或者炸毁用户内存并让模型服务提供数据对象的(深层)克隆。在后一种情况下,您还必须制定一个约定:“模型服务getter必须提供克隆。”但也许该模型是由其他开发人员开发的,然后是控制器或视图,单元测试可以更容易地实现这一点 - 如果有一个常规要测试,如果模型服务获取者提供克隆:)。
这种方法的优点是,您可以在Angular表达式和$ watch语句中使用getter函数,而不必处理事件。
答案 2 :(得分:0)
使用angularjs掌握Web应用程序
在整个AngularJS框架中,只有三个事件 已发出($ includeContentRequested,$ includeContentLoaded, $ viewContentLoaded),以及正在播放的七个事件 ($ locationChangeStart,$ locationChangeSuccess,$ routeUpdate, $ routeChangeStart,$ routeChangeSuccess,$ routeChangeError,$ destroy)。 如您所见,范围事件非常谨慎地使用,我们应该这样做 之前评估其他选项(主要是双向数据绑定) 发送自定义事件。