如何使用pushState
在应用程序的整个生命周期中保存URL参数状态?
- 页面加载
- 通过
href
转到"/search"
submitSearch()
通过过滤字段,其中$location.search(fields)
- 通过
href
转到"/anotherPage"
- 通过
href
返回"/search"
- 搜索参数设置为上次的值
这是某个地方的内置功能吗?
如果没有,最好的办法是什么?
如果您计划通过pushState访问一个主要为单页的网站,您可能需要深入了解$routeProvider(http://docs.angularjs.org/api/ngRoute.%24routeProvider)。
要深入了解兔子洞,我建议查看ui路由器模块:(https://github.com/angular-ui/ui-router)$stateProvider(来自ui路由器)和$routeProvider的工作原理非常相似,因此有时ui路由器文档可以提供在$routeProver的糟糕文档中找不到的见解。
我建议浏览五页的ui路由器文档(https://github.com/angular-ui/ui-router/wiki)一页一页。
在所有这些序言之后,这里是实用的:您将建立一个保存历史数据的工厂,并使用$routeProvider/$stateProvider中定义的控制器来访问和操作这些数据。
注:工厂是一项服务。服务并不总是工厂。名称空间为:
angular.module.<servicetype[factory|provider|service]>.
这篇文章解释了服务类型:https://stackoverflow.com/a/15666049/2297328.重要的是要记住,他们都是单身人士。
例如:
var myApp = angular.module("myApp",[]);
myApp.factory("Name", function(){
return factoryObject
});
代码看起来像:
// Warning: pseudo-code
// Defining states
$stateProvider
.state("root", {
url: "/",
// Any service can be injected into this controller.
// You can also define the controller separately and use
// "controller: "<NameOfController>" to reference it.
controller: function(History){
// History.header factory
History.pages.push(History.currentPage);
History.currentPage = "/";
}
})
.state("search", {
url: "/search",
controller: function(History, $routeParams) {
History.lastSearch = $routeParams
}
});
app.factory('<FactoryName>',function(){
var serviceObjectSingleton = {
pages: []
currentPage: ""
lastSearch: {}
}
return serviceObjectSingleton
})
如果你想知道$routeProvider和$stateProvider之间的区别是什么,那只是$stateProvider有更多的功能,主要是嵌套的状态和视图。。。我想。
最简单的方法是使用cookie,angularjs为此提供包装服务。当你进入"/search"时,只需用"$cookieStore.put()"保存当前的URL参数,一旦你回来,你就可以用"$cookieStore.get()"得到你需要的东西。
请参阅angularjs cookie商店上的文档
我制作了一个locationState
服务,您只需给它想要持久化的值,它就会将它们存储在URL中。因此,您可以在应用程序中存储所有路线上的所有状态。
这样使用:
angular.module('yourapp')
.controller('YourCtrl', function ($scope, locationState) {
var size = locationState.get('size');
;
// ... init your scope here
if (size) {
$scope.size = size;
}
// ...and watch for changes
$scope.$watch('size', locationState.setter('size'));
}
这是代码:
// Store state in the url search string, JSON encoded per var
// This usurps the search string so don't use it for anything else
// Simple get()/set() semantics
// Also provides a setter that you can feed to $watch
angular.module('yourapp')
.service('locationState', function ($location, $rootScope) {
var searchVars = $location.search()
, state = {}
, key
, value
, dateVal
;
// Parse search string
for (var k in searchVars) {
key = decodeURIComponent(k);
try {
value = JSON.parse(decodeURIComponent(searchVars[k]));
} catch (e) {
// ignore this key+value
continue;
}
// If it smells like a date, parse it
if (/[0-9T:.-]{23}Z/.test(value)) {
dateVal = new Date(value);
// Annoying way to test for valid date
if (!isNaN(dateVal.getTime())) {
value = dateVal;
}
}
state[key] = value;
}
$rootScope.$on('$routeChangeSuccess', function() {
$location.search(searchVars);
});
this.get = function (key) {
return state[key];
};
this.set = function (key, value) {
state[key] = value;
searchVars[encodeURIComponent(key)] = JSON.stringify(value);
// TODO verify that all the URI encoding etc works. Is there a mock $location?
$location.search(searchVars);
};
this.setter = function (key) {
var _this = this;
return function (value) {
_this.set(key, value);
};
};
});