History新API产生的意义
一、从哪里得知History新API
在Backbone的History模块涉及到一个pushState的参数,一直搞不太懂这个东西玩什么鬼花样。看文档说是HTML5 History的一个新API。想看一下History究竟为了解决什么问题而去增加这一部分内容。
说一下一个大家熟知的场景:
现在采用ajax的网站到处都是,到了一个页面,可以让你进行搜索一些商品,按商品的品种、品牌等进行搜索,当你输入完之后,点击搜索的按钮,页面的显示结果的区域会给你异步获取当前的搜索结果,当然你不会一下就搜到你的宝贝,你还会再进行进一步的细化搜索,可能根据颜色、价钱、优惠等再进行搜索,然后点击搜索按钮,页面再显示结果,这样来来往往,你可能重复这些步骤,然后在某个时刻,你搜了一阵子之后你发现之前某个条件搜出来的结果是最符合你心意的,而这时你想到后退,然后点击浏览器的后退按钮,但你的页面需要重新刷新一次,虽然网站给你做了事,但体验不好,较好的体验应该是后退的时候也能异步去刷新获取数据,而不是一整个页面去刷。
场景的出现原因:
在我们输入搜索条件进行搜索的时候,程序一般会将参数传到我们的网址,并且作为参数传到后台去调用相应的方法,把数据拿出来显示,好像原来访问的是一个地址,搜索后,地址栏的地址发现比原来多出了很多参数,这里多了的参数附加于地址栏上,在没有新API的history对象在返回操作的时候,它变更了浏览器的地址,同时也做了一个刷新操作,这种机制强制了刷新页面,这种机制是祸根。
如何去解决这种不好的机制:
假如浏览器在做前进后退的时候,好像一些需要向网址附带参数去匹配后台方法来实现异步获取数据的时候,能让我们可以将这些变更后的网址产生一个历史节点,当某个时刻返回到那个历史节点时,浏览器帮我做两个事,一个是变更我的浏览地址,第二个是不要刷新页面而是抛出一个事件,事件传入的参数带了历史节点保存的信息,可以理解为保存用于搜索的变量,如之前提到的spm、initiaive_id这些变量,这样我们可以在事件内做异步操作来获取用户的结果并显示于页面,达到用户获取数据的同时,采用了无刷新技术,这样更能保持流程上的统一感,体验更佳!而History能很好满足我们的需求,在HTML5 中引入了History的pushState、replaceState这些新的方法、当然还有其他方法和属性,旨在提供一种更好的方式处理之前在场景中遇到的问题的。
HTML5 的技术主旨:
我觉得HTML5不是在做华而不实的东西,也不是做了颠覆性的革命,就是很朴实地,很自然地,本应该地改良优化用户体验的事而去的。
二、基础知识
如何快速了解其构成?
最好的办法你就是用firebug在代码中打个断点,在监控台上去观察它。
属性:
length--历史节点的个数
方法:
back() -- 后退一页 (相当于点击浏览器的后退按钮)
forward()-- 前进一页(相当于点击浏览器的前进按钮)
pushState()-- 有三个参数,第一个是jason格式参数,这个参数会传到onpopstate事件,这个参数等价与事件参数event.state,第二个是title,字符串格式,第三个是变更后的url。这个方法会使history.length属性增加1.
replaceState()-- 和pushState类似,唯一不同的是它不会让history.length增加1。对这个length这个属性不产生任何作用。
go()-- 一个参数正数表示前进的页数,负数则表示后退的页数
事件:
window.onpopstate-- 当通过前进按钮或者后退按钮(也可以是通过history.back(),和history.forward(),或者go())点击后,刚好同之前history的历史节点吻合时会触发。
三、举例应用
这个例子需要PHP作为后端,来更好演示在历史节点的后退或者前进操作依然可以无刷新ajax获取数据。
部署情况:我将其发布到apache服务器,端口为86的。首先从http://127.0.0.1:86/index.html地址打开浏览
提示:我这里是用了php的集成开发环境,按道理初学是不建议使用,如果只是纯粹去模拟一下效果,达到更好去理解history新API产生的意义的话,用一下也是对的。这个集成开发环境名字为:WampServer2.0f.exe。
整个目录结构为
|
|--js
| --jquery.js
|--index.html
|--main.php
文件一:
<a href="javascript:" id="pushstate">history.pushState(data, title [, url])</a><br> <a href="javascript:" id="replacestate">history.replaceState(data, title [, url]) </a><br> <a href="javascript:" id="onpopstate">window.onpopstate</a><br> <a href="javascript:" id="back">返回</a> <div id="loaddiv"></div> <script src="js/jquery.js"></script>
<script>
$(function(){
var loaddiv = $('#loaddiv');
/*
1.当回到某个节点时会触发onpopstate 事件,如回到http://127.0.0.1:86/main.php?stype=push历史节点时,参数e.state为之前 history.pushState({title:'push'},"",'main.php?stype=push');传过来的{title:'push'},我们可以通过"main.php?stype=" + e.state.title来获取请求信息,异步把数据从main.php拿回来。实现了一个后退操作无刷新获取数据的应用举例。
*/
window.onpopstate = function(e){
if( !!e.state ){
if(e.state.title){
loaddiv.load("main.php?stype=" + e.state.title);
}
}else{
loaddiv.html("");
}
};
/*
1.这里我们对三个a标签绑定了事件,load是jquery的方法,用于异步获取页面的内容并且将其插入到相应的元素对象内
,如loaddiv.load('main.php?stype=push');是请求http://127.0.0.1:86/main.php?stype=push页面的内容,在main.php的后端脚本会获取stype这个参数,并输出对应的字符串,用次来模拟从后台获取数据。
2. history.pushState({title:'push'},"",'main.php?stype=push')是将这个请求URL添加到历史节点中,并穿了一个参数{title:'push'}参数。
*/
$('#pushstate').click(function(){
loaddiv.load('main.php?stype=push');
history.pushState({title:'push'},"",'main.php?stype=push');
});
$('#replacestate').click(function(){
loaddiv.load('main.php?stype=replace');
history.replaceState({title:'replace'},"",'main.php?stype=replace');
});
$('#onpopstate').click(function(){
loaddiv.load('main.php?stype=onpop');
history.pushState({title:'onpop'},"",'main.php?stype=onpop');
});
$('#back').click(function(){
history.back();
});
});
文件二:
main.php:
$type = $_REQUEST['stype'];
switch($type){
case 'push' :
echo 'history.pushState(data, title [, url]):返回往历史记录堆栈顶部添加一条记录;data会在onpopstate事件触发时作为参数传递过去;title为页面标题,当前所有浏览器都会 忽略此参数;url为页面地址,可选,缺省为';
break;
case 'replace' :
echo 'history.replaceState(data, title [, url]) :更改当前的历史记录,参数同上';
break;
case 'onpop' :
echo 'window.onpopstate:响应pushState或replaceState的调用;';
break;
}
?>
四、我的疑问
虽然replaceState方法没有对历史节点增加节点,按常理history对象应该不会知道曾经去过那个URL,因为它压根没有保存那个历史节点,为什么还能返回到那个节点呢?
本文来源 我爱IT技术网 http://www.52ij.com/jishu/4841.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)

楼主 你的第四个疑问解决了么? 我现在也有这个问题啊