使用服务在控制器 AngularJs 之间共享数据
Share data between controllers AngularJs with Services
背景
我正在制作服务,其中有一个要在两个控制器之间共享的列表。首先,我遵循了有关服务的本教程:
并且我成功创建并执行了 Plunker 的基础教程:
问题
这里的问题是,当我单击表单按钮时,我需要向我的服务器发出 HTTP GET 请求,并在收到响应时更新服务列表。
为此,我首先尝试使用以下 Plunker 修改:
代码的笑话可以在服务中看到:
// Create the factory that share the Fact
app.factory('ListService', function($http) {
var list = {};
list.data = [];
list.request = function(theHairColor) {
var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
console.log(theUrl);
$http({
method: 'GET',
url: theUrl,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}).then(function successCallback(response) {
list.data = response.data.entries; //does not work
console.log(response.data.entries);
}, function errorCallback(response) {
console.log('Error: ' + response);
});
};
return list;
});
如果你尝试过,你会发现它根本不起作用,我真的不明白为什么。在我之前的一个问题中,有人向我解释说它与引用有关,我应该将 list.data = response.data.entries; //does not work
替换为以下内容:
//this works but is rather flimsy ....
list.data.length = 0;
Object.assign(list.data, response.data.entries);
这确实有效,但我发现它相当违反直觉:
还给出了另一个建议,我应该将 gnomeList
控制器更改为:
app.controller("gnomeList", function(ListService) {
var self = this;
self.listService = ListService;
});
然后直接遍历服务列表:
<div ng-controller="gnomeList as listCtrl">
<p ng-repeat="gnome in listCtrl.listService.data">{{ gnome.id }}: {{ gnome.name }}</p>
</div>
这也有效,但将控制器直接附加到服务:
问题:
- 是否有任何其他方法可以使我的第一个代码示例(不起作用)起作用?
- 以下哪种解决方案更可取,为什么? (哪个更角度?)
所以这不起作用?
list.request = function(theHairColor) {
var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
console.log(theUrl);
$http({
method: 'GET',
url: theUrl,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}).then(function success(data) {
list.data = data;
console.log(data);
return data;
});
};
那将是我们过去使用的结构(我们现在使用 Restangular),但是这个 link 是一个 good page 查看 $http 会对你有所帮助。
问题是您最初将数据复制到 gnomeList 中,并且它是按值传递的。
app.controller("gnomeList", function(ListService) {
var self = this;
self.list = ListService.data;
});
当您的控制器在这里初始化时,它会将 ListService.data
的副本放入 self.list
。但是,当更新服务中的值时,此控制器不会再次初始化,因此不会更新该值。
javascript 中的对象通过引用传递。就像您所说的,您可以直接将服务放在范围内以使用其数据,或者您只需在对象上设置属性,然后再将它们设置在您的范围内。 (Plunkr)
Javascript
app.controller("gnomeList", function(ListService) {
var self = this;
self.list = ListService.value; // value is an object
});
// Create the factory that share the Fact
app.factory('ListService', function($http) {
var list = {};
list.value = {};
list.request = function(theHairColor) {
var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
console.log(theUrl);
$http({
method: 'GET',
url: theUrl,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}).then(function successCallback(response) {
list.value.data = response.data.entries; // extend value object
}, function errorCallback(response) {
console.log('Error: ' + response);
});
};
return list;
});
HTML
<div ng-controller="gnomeList as listCtrl">
<p ng-repeat="gnome in listCtrl.list.data">{{ gnome.id }}: {{ gnome.name }}</p>
</div>
此外,最好使用内置 angular.extend 来扩展对象。
背景
我正在制作服务,其中有一个要在两个控制器之间共享的列表。首先,我遵循了有关服务的本教程:
并且我成功创建并执行了 Plunker 的基础教程:
问题
这里的问题是,当我单击表单按钮时,我需要向我的服务器发出 HTTP GET 请求,并在收到响应时更新服务列表。
为此,我首先尝试使用以下 Plunker 修改:
代码的笑话可以在服务中看到:
// Create the factory that share the Fact
app.factory('ListService', function($http) {
var list = {};
list.data = [];
list.request = function(theHairColor) {
var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
console.log(theUrl);
$http({
method: 'GET',
url: theUrl,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}).then(function successCallback(response) {
list.data = response.data.entries; //does not work
console.log(response.data.entries);
}, function errorCallback(response) {
console.log('Error: ' + response);
});
};
return list;
});
如果你尝试过,你会发现它根本不起作用,我真的不明白为什么。在我之前的一个问题中,有人向我解释说它与引用有关,我应该将 list.data = response.data.entries; //does not work
替换为以下内容:
//this works but is rather flimsy ....
list.data.length = 0;
Object.assign(list.data, response.data.entries);
这确实有效,但我发现它相当违反直觉:
还给出了另一个建议,我应该将 gnomeList
控制器更改为:
app.controller("gnomeList", function(ListService) {
var self = this;
self.listService = ListService;
});
然后直接遍历服务列表:
<div ng-controller="gnomeList as listCtrl">
<p ng-repeat="gnome in listCtrl.listService.data">{{ gnome.id }}: {{ gnome.name }}</p>
</div>
这也有效,但将控制器直接附加到服务:
问题:
- 是否有任何其他方法可以使我的第一个代码示例(不起作用)起作用?
- 以下哪种解决方案更可取,为什么? (哪个更角度?)
所以这不起作用?
list.request = function(theHairColor) {
var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
console.log(theUrl);
$http({
method: 'GET',
url: theUrl,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}).then(function success(data) {
list.data = data;
console.log(data);
return data;
});
};
那将是我们过去使用的结构(我们现在使用 Restangular),但是这个 link 是一个 good page 查看 $http 会对你有所帮助。
问题是您最初将数据复制到 gnomeList 中,并且它是按值传递的。
app.controller("gnomeList", function(ListService) {
var self = this;
self.list = ListService.data;
});
当您的控制器在这里初始化时,它会将 ListService.data
的副本放入 self.list
。但是,当更新服务中的值时,此控制器不会再次初始化,因此不会更新该值。
javascript 中的对象通过引用传递。就像您所说的,您可以直接将服务放在范围内以使用其数据,或者您只需在对象上设置属性,然后再将它们设置在您的范围内。 (Plunkr)
Javascript
app.controller("gnomeList", function(ListService) {
var self = this;
self.list = ListService.value; // value is an object
});
// Create the factory that share the Fact
app.factory('ListService', function($http) {
var list = {};
list.value = {};
list.request = function(theHairColor) {
var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
console.log(theUrl);
$http({
method: 'GET',
url: theUrl,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}).then(function successCallback(response) {
list.value.data = response.data.entries; // extend value object
}, function errorCallback(response) {
console.log('Error: ' + response);
});
};
return list;
});
HTML
<div ng-controller="gnomeList as listCtrl">
<p ng-repeat="gnome in listCtrl.list.data">{{ gnome.id }}: {{ gnome.name }}</p>
</div>
此外,最好使用内置 angular.extend 来扩展对象。