问题描述
在我学习 angular 的过程中,有两个问题困扰着我:
Two problems have troubled me as I have learned angular:
如何在用户刷新页面或点击后退按钮时恢复状态?
如何在属于不同控制器的范围之间共享数据?
下面我展示了一个使用客户端会话存储的简单解决方案.它允许共享公共数据并在用户刷新页面或点击后退按钮后自动恢复状态.
Below I show a simple solution that makes use of client-side session storage. It allows for both the sharing of common data and the automatic restoration of state after a user refreshes the page or hits the back button.
注意:事实证明,以下解决方案对于回答以下问题至关重要:
Note: The solution below proved essential to answer the following question:
如何让后退按钮与 AngularJS ui-router 状态机配合使用?
推荐答案
解决方案依赖于如下所示的 SessionService
类.语法是咖啡脚本.
The solution depends on the SessionService
class shown below. The syntax is coffeescript.
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
属性(简单的 bool)和 user
属性(一个复杂的对象).这些属性的值在使用 javascript 提供的客户端本地 sessionStorage
对象存储/检索时会自动字符串化/解析.
The SessionService
class defines the isAuthenticated
property (simple bool) and the user
property (a complex object) . The values of these properties are automatically stringified / parsed as they are stored / retrieved using the client-side local sessionStorage
object supplied by javascript.
您可以根据需要添加更多属性.像 $rootScope
一样,您可以谨慎地添加属性.与 $rootScope
不同,属性值在页面刷新或单击后退按钮后仍然可用.
You add more properties as required. Like $rootScope
you add properties sparingly. Unlike $rootScope
the property values are still available after a page refresh or back button click.
该服务允许向其注册任意数量的范围.注册作用域后,sessionStorage
中的所有存储值都会自动分配给该作用域.通过这种方式,所有已注册的作用域始终可以访问所有会话属性.
The service allows any number of scopes to be registered with it. When a scope is registered all the stored values in sessionStorage
are automatically assigned to that scope. In this way all the registered scopes always have access to all the session properties.
更新属性值时,所有注册的范围都会更新其对应的值.
When a property value is updated, all the registered scopes have their corresponding values updated.
当 angular 销毁作用域时,它会自动从注册作用域列表中删除,以节省资源.
When angular destroys a scope it is automatically removed from the list of registered scopes to save wasting resources.
如果用户刷新页面或点击后退按钮,Angular 应用程序将被迫重新启动.通常这意味着您必须重建您当前的状态.SessionService
会自动为您执行此操作,因为在应用程序初始化期间注册时,每个范围都会从本地存储恢复其值.
If a user refreshes the page or hits the back button then the angular application is forced to restart. Normally this would mean you would have to reconstruct your current state. The SessionService
does this for you automatically as each scope will have its values restored from local storage when they are registered during the app initialisation.
所以现在很容易解决在范围之间共享数据以及在用户刷新或点击后退按钮时恢复值的问题.
So now it is easy to solve the problem of both sharing data between scopes as well as restoring values when the user refreshes or hits the back button.
以下是一些示例 Angular 代码,展示了如何使用 SessionService
类.
Here is some sample angular code that shows how to use the SessionService
class.
在某个控制器中向 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}}
这篇关于如何使用 AngularJS 单页应用程序处理页面刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!