Javascript 角度:通过服务或更好的方法更新不同的控制器
我有一个用户服务Javascript 角度:通过服务或更好的方法更新不同的控制器,javascript,angularjs,Javascript,Angularjs,我有一个用户服务 angular.module('mango.services', []) .factory('UserService', function() { var user = { id: null, name: 'anonymous.' }; function getUser(){ return user; } functio
angular.module('mango.services', [])
.factory('UserService', function() {
var user = {
id: null,
name: 'anonymous.'
};
function getUser(){
return user;
}
function setUser(val){
user = val;
}
return {
getUser: getUser,
setUser: setUser,
}
});
导航控制器
.controller('NavbarController', ['$scope','$location','UserService', function($scope, $location, UserService){
$scope.isActive = function (viewLocation) {
return viewLocation === $location.path();
};
$scope.username = UserService.getUser().name;
}])
还有一个UserController,其中有registerUser和logiuser函数
.controller('UserController', ['$scope', '$http', 'UserService', function($scope, $http, UserService) {
$scope.loginUser = function(){
$http.post('/api/1.0/user/authenticate', $scope.user)
.success(function(data,status,headers,config){
if (data["valid"] === true) {
UserService.setUser(data.user);
} else {
$scope.flashes = data.flashes;
$scope.user.password = "";
}
})
}
还有HTML
<li ng-switch="username">
<a ng-class="{ active: isActive('/user/login')}" href="#/user/login" ng-switch-when="anonymous."><i class="fa fa-sign-in"></i> Sign in</a>
<a ng-class="{ active: isActive('/user/logout')}" href="#/user/logout" ng-switch-default><i class="fa fa-sign-out"></i> Sign out</a>
</li>
如您所见,如果data.valid为true,我将尝试设置UserService的用户
服务器正在返回有效的json对象
但是NavbarController中的用户名值仍然是“匿名的”
我对JS不是很有经验,但我读了一些关于广播和观看的东西。我相信这可能是正确的方法。但也许有更好的
我相信它不起作用的原因是因为工厂退回了一个单身汉。但是使用工厂是没有意义的
所以本质上我想要的是,如果凭据有效,请在客户端应用程序范围内设置user.name user.id。稍后,它应该通过“检查客户端用户是否有效”服务。我的会话cookie已加密。但这超出了问题的范围
我现在只需要从UserController设置应用程序的用户数据,或者更确切地说是NavbarController的用户数据。如何做到这一点,以便它也会更新DOM aka ng开关以获得不同的值。您确实需要一个
$watch
er来同步NavbarController
和UserService
中的$scope.username=UserService.getUser().name
仅在初始化控制器时设置$scope.username
的初始值:
$scope.$watch(
函数(){return UserService.getUser().name;},
函数(newVal){
$scope.username=newVal;
}
);
工厂实际上被设计成应用程序中的一个单例,在这里您应该保存应用程序的状态(即您的模型,如用户
模型)。控制器是短暂的,每次创建模板时都会重新创建
但是,如果您有一个长寿命的控制器(如NavbarControll
),则使用$watch
在服务和控制器之间保持同步的责任在于程序员
在某些情况下,当需要控制器间通信(不一定涉及型号)时,广播消息非常有用。它不起作用,因为您没有创建某种类型的绑定:使用$scope.username=UserService.getUser().name
您可以在该时刻获得用户名(这是一个匿名的
)并永远保持它。解决方法之一是使用手表。在NavbarController中,将以前的代码替换为:
$scope.$watch(
function() {
return UserService.getUser().name;
},
function(newval) {
$scope.username = newval;
}
);
这将导致您的应用程序在每个摘要周期中调用一个函数。这个函数调用并不慢,所以这无关紧要
如果您不希望出现这种开销,也可以使用事件来实现。在NavbarController中:
$scope.username = UserService.getUser().name;
$scope.on("loggedIn", function(event, newUserName) {
$scope.username = newUserName;
});
在UserController中(将$rootScope
添加到依赖项中):
- 您可以在不使用$watch的情况下使用相同的方法
我编写了一个简短的函数,让您可以将数据放入对象中,而无需替换它。
您可以在您的服务中使用它。这样您就不需要使用手表。您可以使用Angular的正常摘要循环。
例如,请参见以下简单控制器和服务:
演示:JSFidde-带有断言测试
控制器:
app.controller('dem',function($scope,me){
$scope.user=me.user; // {name:'user name'}
})
// The function it is like a=b,
// but keeping the object in his original memory position.
function cloneInto(a,b){
var i
for (i in a){
if(typeof a[i]!='object') //For supporting deep-copy
delete a[i]
}
for (i in b){
if (typeof b[i]=='object'){
if(!a[i]) a[i]={}
cloneInto(a[i],b[i])
}
else{
a[i]=b[i]
}
}
}
每次更改用户名时,控制器将自动更改,无需监视
服务
.factory('me',function($timeout){
var obj={}
obj.user={name:'hello'}
$timeout(function(){ //Example of change the data
newUser={name:'israel'}
cloneInto(obj.user,newUser)
},1000)
return obj
})
我编写的克隆函数:
app.controller('dem',function($scope,me){
$scope.user=me.user; // {name:'user name'}
})
// The function it is like a=b,
// but keeping the object in his original memory position.
function cloneInto(a,b){
var i
for (i in a){
if(typeof a[i]!='object') //For supporting deep-copy
delete a[i]
}
for (i in b){
if (typeof b[i]=='object'){
if(!a[i]) a[i]={}
cloneInto(a[i],b[i])
}
else{
a[i]=b[i]
}
}
}
你试过使用服务而不是工厂吗?我相信服务使用单个对象,而工厂每次注入都会生成新的引用。谢谢,我选择Nikos one是因为它也有广播示例(比你快3分钟).我还没决定..因为你解释得更好。所以我同意了他的答案,并对你的答案投了更高的票~@user2312578当然,不过你也应该对他的答案投更高的票。而且,我不确定你是否正确计算出谁更快。:)谢谢,事件是更好的解决方案$广播和$on类似于我熟悉的Qt的信号/插槽。