之前在做分页的时候经常会遇到一个问题,通过URL传递分页参数会导致页面加载过慢,页面有明显刷新的体验。而通过ajax访问虽然仅仅进行了局部刷新,但是用户很难直接通过 URL到达自己想要的页数,或者筛选的结果页面;用户通过浏览器返回也无法回到上一个页面对应的页码。
URL有一个属性叫hash,中文名称哈希。
location是javascript里边管理地址栏的内置对象,比如location.href就管理页面的url,用location.href=url就可以直接将页面重定向url。而location.hash则可以用来获取或设置页面的标签值。
通过方法或者href="#xx"来改变hash是不会导致页面刷新或者重新加载的。
这就意味着可以通过hash来存储对应页码或者筛选条件。
window.addEventListener('hashchange', function(e) { console.log(e.oldURL); console.log(e.newURL); }, false);
当然手动书写代码是可以监听hash的变化的。
window.location.hash
主动获取hash也是没有任何问题的。
但是这样书写是很麻烦的。
这里介绍一个js插件angular.js
其实,最早听说angular.js我是排斥的,因为对于我而言,灵活多变无限开放的javascript是我之所以能够学好网页的一个基本条件,我的代码奔放巧妙,不拘泥于一种实现方法。
但是,angular.js中的路由模块是我觉得为数不多好用的地方。
angular.js
一种mvc的前端框架,通过强有力的模块思维构成的一个框架。那把显示的页面数据当成是一个模型(M),通过控制器(C)注入到其他控制器或者显示在页面(V)上。类似于java上的mvc框架。angular.js的继承功能更多的用于特别多而繁琐联动的页面上面
ngRoute
ngRoute是angular.js的一个模块,它是基于hash实现的。原理也是通过监听hash的变化,获取对应的参数。
这个是一个范例,我在hash中传递了3对参数{page,color,price}。
那请求的页面是什么呢,当然是分页的ajax,只是这里做了一个小变种。改变以往请求的结果是json而是html结构,这就是一个现成的html页面了。
这里我需要回调3个参数,这里用了一个很蠢的办法,控制器。
把结果对应的参数赋予全局变量。
完整代码如下
<div class="website-list-content clearfix" ng-app='stoneRouteApp' ng-view></div>
var page = 1; var color = ''; var price = ''; $('#priceSelect').find('li[role="presentation"]').click(function() { $('li[role="presentation"]').not(this).removeClass('active'); var _this = $(this); var _a = _this.find('a'); var value = _a.attr('value'); var name = _a.text(); $('#priceInput').val(value); $('#priceName').text('Price ' + (name == 'All Group' ? '' : name)); price = value; location.hash = '#!/page/' + page + colorFun() + priceFun(); }) $('#colorSelect').find('li[role="presentation"]').click(function() { $('li[role="presentation"]').not(this).removeClass('active'); var _this = $(this); var _a = _this.find('a'); var aColor = _a.css('color'); var value = _a.attr('value'); var name = _a.text(); $('#colorInput').val(value); $('#colorName').text('Color ' + value); color = value; location.hash = '#!/page/' + page + colorFun() + priceFun(); }) function colorFun() { if(color == '') { return '' } else { return '/color/' + color; } } function priceFun() { if(price == '') { return '' } else { return '/price/' + price; } } angular.module('stoneRouteApp', ['ngRoute']) .controller('returnRouteParams', function($scope, $route) { var pathParams = $route.current.pathParams; if(pathParams.paging != undefined) { page = pathParams.paging; } if(pathParams.color != undefined) { color = pathParams.color; } if(pathParams.price != undefined) { price = pathParams.price; } }) .config(['$routeProvider', function($routeProvider) { $routeProvider .when('/', { templateUrl: 'stoneList.html' }) .when('/page/:paging', { templateUrl: function($routeParams) { return httpRequest($routeParams); }, controller: 'returnRouteParams', }) .when('/page/:paging/color/:color', { templateUrl: function($routeParams) { return httpRequest($routeParams); }, controller: 'returnRouteParams', }) .when('/page/:paging/price/:price', { templateUrl: function($routeParams) { return httpRequest($routeParams); }, controller: 'returnRouteParams', }) .when('/page/:paging/color/:color/price/:price', { templateUrl: function($routeParams) { return httpRequest($routeParams); }, controller: 'returnRouteParams', }) .when('/page/:paging/price/:price/color/:color', { templateUrl: function($routeParams) { return httpRequest($routeParams); }, controller: 'returnRouteParams', }) .otherwise({ //redirectTo: '/' }); }]); function httpRequest(routeParams) { var requestLink = 'stoneList.html?' if(routeParams.paging == undefined) { requestLink += 'page=1'; } else { requestLink += 'page=' + routeParams.paging; } if(routeParams.color != undefined) { requestLink += '&color=' + routeParams.color; } if(routeParams.price != undefined) { requestLink += '&price=' + routeParams.price; } return requestLink; }