当我学到角度时,有两个问题困扰着我:
当用户刷新页面或点击后退按钮时,如何恢复状态?
如何在属于不同控制器的合并范围之间共享数据?
下面我展示了一个使用客户端会话存储的简单解决方案。在用户刷新页面或点击后退按钮后,它既允许共享公共数据,又可以自动恢复状态。
注意:事实证明,以下解决方案对于回答以下问题至关重要:
如何获得“后退”按钮以与AngularJSui路由器状态机一起使用?
解决方案取决于SessionService下面显示的类。语法是coffeescript。
SessionService
SessionService类别
class SessionService scopes:[] setStorage:(key, value) -> scope[key] = value for scope in @scopes value = if value is undefined then null else JSON.stringify value sessionStorage.setItem key, value getStorage:(key)-> sessionValue = sessionStorage.getItem key if sessionValue == "undefined" return null JSON.parse sessionValue register:(scope)-> for key, value of sessionStorage scope[key] = if value? and value != "undefined" then JSON.parse(value) else null @scopes.push scope scope.$on '$destroy', => @scopes = @scopes.filter (s) -> s.$id != scope.$id clear: -> @setStorage(key, null) for key of sessionStorage isAuthenticated: -> @accessor 'isAuthenticated', value user:(value=null) -> @accessor 'user', value # other storage items go here accessor:(name, value)-> return @getStorage name unless value? @setStorage name, value angular .module 'app.Services' .service 'sessionService', SessionService
在SessionService类定义的isAuthenticated属性(简单布尔)和user属性(一个复杂的对象)。这些属性的值在使用sessionStoragejavascript提供的客户端本地对象存储/检索时会自动进行字符串化/解析。
isAuthenticated
user
sessionStorage
您 根据需要 添加 更多属性 。就像$rootScope您少量添加属性一样。与$rootScope属性不同,在刷新页面或单击后退按钮后,属性值仍然可用。
$rootScope
该服务允许向其注册任意数量的范围。注册范围后,所有存储的值sessionStorage将自动分配给该范围。这样,所有注册的作用域始终可以访问所有会话属性。
更新属性值时,所有注册的作用域都会更新其对应的值。
当angular破坏范围时,它将自动从已注册范围的列表中删除,以节省浪费的资源。
如果用户刷新页面或单击后退按钮,则强制角度应用程序重新启动。通常,这意味着您将必须重构当前状态。将SessionService自动为您做到这一点,因为每个范围将是从本地存储恢复它的价值时,他们的应用程序初始化期间注册。
因此,现在很容易解决在范围之间共享数据以及在用户刷新或单击后退按钮时还原值的问题。
这是一些示例角度代码,显示了如何使用SessionService该类。
在某些Controller中向SessionService注册范围
angular .module 'app' .controller 'mainCtrl', ($scope, $state, session, security) -> #register the scope with the session service session.register $scope #hook up the 'login' method (see security service) $scope.login = security.login # check the value of a session property # it may well be true if the page has been refreshed if session.isAuthenticated $state.go('home') else $state.go('login')
在服务中设置会话值
class SecurityService @$inject:['$http','sessionService', 'api'] constructor:(@http, @session, @api) -> login:(username, password) => @http.get "#{@api.base}/security/login/credentials/#{username}/#{password}" .success (user)=> @session.isAuthenticated = true @session.user = user .error (ex)=> # process error angular .module 'app' .service 'securityService', SecurityService
在UI中使用会话值(Jade模板)
div(ng-show="isAuthenticated") div Hello {{user.Name}}