Javascript 用户登录后如何动态更新指令?
我有一个带有导航条指令和基本注册/登录功能的应用程序。我想在用户登录后更改导航栏上的一些单词(从“注册/登录”改为“注销”),但我想不出最好的(甚至是一种)方法。我尝试将要更改的变量/绑定的值设置为在用户登录时更新的工厂,但这不起作用,指令也不会用其新值更新 我的代码附在下面,具体的解决方案是赞赏的,但不是真的必要的,如果有人可以告诉我正确的方向,如何做到这一点,这将是非常有帮助的 我尝试过的解决方案:Javascript 用户登录后如何动态更新指令?,javascript,angularjs,twitter-bootstrap,angularjs-directive,Javascript,Angularjs,Twitter Bootstrap,Angularjs Directive,我有一个带有导航条指令和基本注册/登录功能的应用程序。我想在用户登录后更改导航栏上的一些单词(从“注册/登录”改为“注销”),但我想不出最好的(甚至是一种)方法。我尝试将要更改的变量/绑定的值设置为在用户登录时更新的工厂,但这不起作用,指令也不会用其新值更新 我的代码附在下面,具体的解决方案是赞赏的,但不是真的必要的,如果有人可以告诉我正确的方向,如何做到这一点,这将是非常有帮助的 我尝试过的解决方案: 工厂 将绑定变量设置为已更新的工厂变量 将绑定变量设置为这些变量的getter语句的输出
- 工厂
- 将绑定变量设置为已更新的工厂变量
- 将绑定变量设置为这些变量的getter语句的输出
- Cookies(除非有人说服我这是解决问题的好方法,否则我宁愿避免使用Cookies)
- 将绑定变量设置为Cookie中的值
- 使用路由,例如在用户登录时将视图从一个导航栏更改为另一个导航栏,尽管这看起来很笨拙
- $rootScope(不完全确定如何使用它,我猜这是错误的用法)
(function() {
'use strict'
angular
.module('app')
.factory('userFactory', userFactory);
userFactory.$inject = ['$http', '$cookies'];
function userFactory($http, $cookies) {
var userStatusLink = '#/user/';
var userStatus = 'Sign Up / Log In';
var service = {
verifyUser: verifyUser,
storeUser: storeUser,
userStatusLink: userStatusLink,
userStatus: userStatus
};
return service;
/* verifyUser() snip */
function storeUser(user) {
$cookies.putObject('user', user); // stores user obj in cookies
userStatusLink = '#/signout/';
userStatus = 'Sign Out';
}
/* solution 2 getters
function getUserStatus() {
return userStatus;
}
function getUserStatusLink() {
return userStatusLink;
}
*/
}
})();
更新:
userFactory.storeUser(user)
在回调中异步发生。成功
回调:
$http.post('someurl').success(function(user) {
userFactory.storeUser(user);
});
您是否尝试复制链接并在布尔方法上使用ng hide/ng show来指示用户是否已登录 首先,登录和注销的显示值应在指令范围内。该小部件(指令)应该拥有登录/注销的所有表示 这听起来好像你真的在试图在指令之间交流。这对于人们来说是一件很常见的事情。您可以在工厂中公开用户值,并使用指令watch进行更改,但这很昂贵,因为它使用了有限数量的手表中的1个 指令之间进行数据通信的常见模式是使用事件。您的工厂或其他指令可以
$rootScope.$emit('user-signed-in',userData)
这会在$rootScope和所有父作用域上发出一个事件,但没有,因此比$broadcast更快
然后,您的指令将侦听事件
$rootScope.on('user-signed-in',function(userData){})
您是否尝试创建getUserStatusLink和getUserStatus方法,并将视图绑定到这些方法
function userFactory($http, $cookies) {
...
var service = {
...
getUserStatusLink: function() {
return userStatusLink;
},
getUserStatus: function() {
return userStatus;
}
};
...
}
然后在导航栏控制器中:
function NavbarController() {
...
vm.accountStatusLink = userFactory.getUserStatusLink();
vm.accountStatus = userFactory.getUserStatus();
}
当userFactory中的userStatusLink和userStatus更新时,这应该完成您希望它完成的任务
更新:
由于正在异步调用storeUser()
方法,因此在设置新值时不会触发另一个摘要周期。因此,您应该强制Angular使用$timeout服务执行摘要循环:
userFactory.$inject = [ ..., '$timeout'];
function userFactory( ..., $timeout) {
...
function storeUser(user) {
...
// forces Angular to perform a digest cycle, thus refreshing your view
$timeout(function() {
userStatusLink = '#/signout/';
userStatus = 'Sign Out';
});
}
...
}
更新2:
使用此实现使用JSFIDLE。我提供了两种方法,您可以看到使用$timeout和不使用$timeout的区别:
我在一个地方错误地引导了您,请更新控制器变量以直接访问该方法,如下所示:
function NavbarController() {
...
// remove the parens at the end of userFactory.getUserStatusLink();
vm.accountStatusLink = userFactory.getUserStatusLink;
// remove the parens at the end of userFactory.getUserStatus();
vm.accountStatus = userFactory.getUserStatus;
}
然后更新视图以实际调用这些方法:
<!-- add parens to view to make it actually call the methods -->
<li><a ng-href="{{ vm.accountStatusLink() }}">{{ vm.accountStatus() }}</a></li>
最终更新:
原来$timeout是不必要的,因为Angular在$http服务的成功回调中执行摘要循环。只需更新视图以直接访问该方法就足以修复它。我没有,但我如何获得该布尔值?我不知道如何更改指令必须使用的值。您可以尝试使用ng show和ng hide-这将是一个很好的解决方案,但我没有办法将“登录”布尔值添加到指令中,由于处理登录的逻辑在不同的控制器中。这似乎是一个复杂/复杂的解决方案,这真的是最好的方法吗?我觉得应该有一种更简单的方式来传递信息。我不想在指令之间进行通信,而只是在工厂和指令之间进行通信。如果不使用事件,唯一可以做的事情就是在工厂上公开
getUser
方法,并在指令中对该函数执行$watch
,如果用户返回,则他们将登录。这意味着您将检查每个角度生命周期中是否存在用户,这是非常频繁的。为什么是复杂的解决方案?非常简单。您尝试过吗?这实际上是我在解决方案2中尝试过的,它的结果似乎与直接将导航栏的变量设置为工厂的变量(正如我现在所做的那样)相同。是否异步调用storeUser?也许您应该尝试在$timeout方法中包装设置userStatusLink和userStatus的位置,以便在设置这些变量后强制Angular运行摘要循环。示例:$timeout(函数(){userStatusLink='blah';userStatus='blah';});所以在.success回调中调用storeUser(),这会被认为是异步调用的吗?(抱歉,这是promises的新功能)是的,这意味着它被异步调用,这意味着它超出了Angular的摘要周期。因此,为了在设置新值后强制Angular执行另一个摘要循环,只需在$timeout
方法中设置它们。我会更新我的答案给你们一个例子。所以,我可以向你们保证,这是有效的,我已经更新了
function NavbarController() {
...
// remove the parens at the end of userFactory.getUserStatusLink();
vm.accountStatusLink = userFactory.getUserStatusLink;
// remove the parens at the end of userFactory.getUserStatus();
vm.accountStatus = userFactory.getUserStatus;
}
<!-- add parens to view to make it actually call the methods -->
<li><a ng-href="{{ vm.accountStatusLink() }}">{{ vm.accountStatus() }}</a></li>