Angularjs 在控制器之间共享异步模型数据
警告:问题很长 我是angularjs的新手,我已经阅读了一些教程和示例,比如angularjs网站上的。将数据导入应用程序并在控制器之间共享数据的推荐方法似乎非常明确。创建一个由所有控制器共享的服务,该服务向服务器发出JSON格式数据的异步请求 这在理论上很好,在只显示一个控制器的极其简单的示例中,或者当控制器不共享依赖于共享数据的逻辑时,这似乎很好。以以下基于年度收入和税收的简单预算应用程序为例: 创建依赖于Angularjs 在控制器之间共享异步模型数据,angularjs,Angularjs,警告:问题很长 我是angularjs的新手,我已经阅读了一些教程和示例,比如angularjs网站上的。将数据导入应用程序并在控制器之间共享数据的推荐方法似乎非常明确。创建一个由所有控制器共享的服务,该服务向服务器发出JSON格式数据的异步请求 这在理论上很好,在只显示一个控制器的极其简单的示例中,或者当控制器不共享依赖于共享数据的逻辑时,这似乎很好。以以下基于年度收入和税收的简单预算应用程序为例: 创建依赖于ngResource的应用程序: var app = angular.module(
ngResource
的应用程序:
var app = angular.module('budgetApp', ['ngResource']);
NetIncomeCtrl处理收入和税务项目并计算净收入的控制器:
app.controller('NetIncomeCtrl', function ($scope, BudgetData) {
var categoryTotal = function (category) {
var total = 0;
angular.forEach(category.transactions, function (transaction) {
total += transaction.amount;
});
return total;
};
$scope.model = BudgetData.get(function (model) {
$scope.totalIncome = categoryTotal(model.income);
$scope.totalTaxes = categoryTotal(model.taxes);
});
$scope.netIncome = function () {
return $scope.totalIncome - $scope.totalTaxes;
};
});
BudgetData使用$resource
从服务器检索JSON数据的服务:
app.factory('BudgetData', function ($resource) {
return $resource('data/budget.json');
});
{
"income": {
"transactions": [
{
"description": "Employment",
"amount": 45000
},
{
"description": "Investments",
"amount": 5000
}
]
},
"taxes": {
"transactions": [
{
"description": "State",
"amount": 5000
},
{
"description": "Federal",
"amount": 10000
}
]
},
}
budget.json包含从服务器返回的json数据:
app.factory('BudgetData', function ($resource) {
return $resource('data/budget.json');
});
{
"income": {
"transactions": [
{
"description": "Employment",
"amount": 45000
},
{
"description": "Investments",
"amount": 5000
}
]
},
"taxes": {
"transactions": [
{
"description": "State",
"amount": 5000
},
{
"description": "Federal",
"amount": 10000
}
]
},
}
然后在我的屏幕上有两个转发器,显示收入和税收项目(您可以编辑),然后计算并显示净收入
这非常有效,这是我在教程中看到的标准方法。然而,如果我仅仅添加一个依赖于某些相同数据和逻辑的控制器,它就会开始分解:
费用控制人TRL最终将计算盈余(净收入-费用)的费用控制人:
budget.json添加费用数据:
"expenses": {
"transactions": [
{
"description": "Mortgage",
"amount": 12000
},
{
"description": "Car Payments",
"amount": 3600
}
]
}
然后在屏幕的另一个部分,我有一个部分使用这个控制器,并使用中继器显示费用项目,然后重新显示净收入,最后显示结果盈余
本例有效,但存在几个问题:
1)在本例中,我设法将控制器的大部分逻辑保留在回调函数之外,但所有控制器都在回调中启动,因为一切都取决于加载的模型。我理解这是javascript的本质,但是angular应该减少所有这些回调的需要,而这看起来并不干净。我能够从回调中提取一些逻辑的唯一原因是angular在引擎盖下用一个假对象替换模型,直到模型加载为止。由于这种“魔力”并不直观,因此很难判断代码是否能按预期工作
人们处理这件事的方式是否一致?我真的不想要一些精心设计的解决方案,让这个101入门应用程序变得非常复杂。是否有一种简单而标准的方法来以某种方式重新构造此代码,以避免如此多的回调并使代码更直观
2)我有一大堆重复的逻辑。categoryTotal
和netIncome
逻辑应仅在一个位置,并在控制器之间共享。这些控制器用于屏幕上完全独立的部分,因此它们不能使用范围继承。即使在使用范围继承时,也可能会出现问题,因为子控制器的范围不能依赖于加载的父范围的模型,即使加载了它自己的模型
categoryTotal
逻辑只是一个辅助函数,它没有直接绑定到模型,所以我不知道在angular中把通用辅助函数放在哪里。对于直接依赖于模型且需要在范围内的netIncome
,可以将其添加到服务或模型中。但是,该服务应该只关注从服务器检索模型,并且模型应该只包含数据,并且尽可能少。而且,这种逻辑似乎属于控制器。有没有一个标准的方法来处理这个问题
3)每次调用服务获取数据时,它都会向服务器发出http请求,即使每次的数据都相同。模型应该在第一个请求之后缓存,因此只有一个请求
我意识到我可以在服务中处理这件事。我可以将模型存储为局部变量,然后在发出请求之前检查该变量以查看数据是否已经存在。奇怪的是,我读过的所有教程都没有提到这一点。此外,我正在寻找一种标准的“角度”处理方法
抱歉,这篇文章太长了。我真的很想保持这个应用程序在101入门级,而不是进入真正复杂的领域,如果可能的话。我也希望有一个标准的“角度”方法来处理这些我还没有遇到的问题
提前谢谢 我就是这样做的。您创建了一个处理数据的服务,如果数据被更改,它将向控制器广播消息。它将获得可以使用BudgetData.data获得的初始数据。如果有人改变数据
.service("BudgetData", function($http, $rootScope) {
var this_ = this, data;
$http.get('wikiArticles/categories', function(response) {
this_.set(response.data);
}
this.get = function() {
return data;
}
this.set = function(data_) {
data = data_;
$rootScope.$broadcast('event:data-change');
}
});
在控制器中,您只需要侦听事件,它将相应地更新范围变量。您可以在任意多个控制器中使用此选项
$rootScope.$on('event:data-change', function() {
$scope.data = BudgetData.get();
}
$scope.update = function(d) {
BudgetData.set(d);
}
谢谢你的快速回复!这涉及到我的第三个问题,但不是前两个问题。这是一种标准的处理方法,还是你想出的办法?我刚刚接触angular,所以我不知道是否有每个人都使用的最佳实践用于此场景。就控制器之间的通信而言,服务和$broadcast是标准方式。因此,对于其他两个问题,即必须在每个控制器中使用回调和在控制器之间共享逻辑,您没有任何建议,比如我的例子中的
netIncome
和categoryTotal
?