- 浏览: 301536 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
阿宁sun:
除了把源码上的注释复制过来,没看到啥东西。。。
初步研究Apache common pool -
jelly:
如果开发游戏,用flash 也有被反编译的危险哦
试读《高性能HTML5》——走向完善的web 客户端 -
zhengjie_dna:
最大的问题是代码 可以获取的 你用soket 完全无法保证安全 ...
试读《高性能HTML5》——走向完善的web 客户端 -
paradigm:
谢谢,我用3分钟找到了这里,一分钟解决。GOOD
我用的关键字 ...
一用subclipse 就导致eclipse莫名奇妙的退出(crash) -
yvhiwssn:
请问我如果将BeanDefinitionBuilder 动态的 ...
动态创建Spring Bean
web应用程序都面临浏览器上的history功能的困扰,前进,后退,刷新,将是你的程序失控,重复提交,丢失数据等等场景让你焦头烂额,运行的好好的程序,被客户随便摆弄一下就错误百出。这些就是客户心智和程序员心智不同产生的冲突。
最初的web程序只是一些静态的网页,一般都通过地址栏的URL地址来进行定位,所以,浏览器集成了很方便的History功能,让你在浏览的历史记录中来回切换。可是,随着复杂应用程序开始越来越多的通过浏览器来作为客户端,噩梦就开始了。
近年来,Ajax技术的兴起为程序设计者和客户提供了不同的技术实现和用户体验,Ajax火了起来,也开始颠覆了传统的web操作和应用传统。但是浏览器并没有相应的来迎合这些变化,这样的话, Ajax 程序也同样的面临浏览器的干扰,而History功能就是其中让人头疼的一个。
越来越多的程序员面临这个问题,开始考虑解决之道,解决的方案五花八门,不过都这能解决问题的一部分,无法从根本上解决这个问题。要根本解决这个问题,只怕需要浏览器的厂商和标准部门针对Ajax一起来想出一个标准化的处理方式。
当然我们没有时间来等待别人来帮助我们解决问题,我这里介绍一下Dojo 解决这个问题的方法,同时研究一下它的实现原理。
需要解决的问题
Ajax程序进行页面内容变化的时候,并没有刷新整个页面也没有改变浏览器地址,所以如果进行以下的操作将会出现无法意料的问题:
行为案例:1search 页面--2search-->3显示列表在本页面--4点击列表中的某条记录--5页面切换-->6所选记录的详细内容页面-->7编辑并保存-->8停留在原页面,提示保存成功-->9返回--.10页面切换-->11search页面
上面的步骤都不会导致浏览器地址变化,因为我们的应用是单页面的frame。
这个案例涉及到两个页面(黑体 1,6),4 个动作(红色 2,4,7,9)
后退/ 前进: 如果在step6的时候,如果浏览器的后退按钮可以点击的话(一般如果你之前没有访问过别的url,那么将不会有后退地址),将不会回到3或者1,而是1之前你访问过的地址。
刷新:如果在step6的时候,你点击刷新,将不会刷新step6所在的页面,因为浏览器的地址没有发生变化,你会发现,页面刷新之后来到了step1.
收藏: 同上,你收藏的step1所在的页面。
客户看到他花钱买的程序却是这样的行为,客户岂不是要疯掉!!!
解决之道
1. dojo
dojo1.0 提供dojo.back 对象来处理这里问题,可以记录页面状态到一个堆栈对象(historyStack)中。但是这个historyStack开始是空的,当我们进入的首页的时候,可以通过setInitialState 方法设置他的第一个状态,如
- dojo.back.setInitialState(currentState);
之后每一次页面状态变化,你都可以将这个状态用书签记录下来,如
- dojo.back.addToHistor(currentState);
state 代表你需要记录的页面状态,一般包括下面几个属性:
back 函数 //当用户点击后退按钮,并且跳转到这个状态的时候将被调用。
forward 函数 // 当用户点击前进按钮,并且跳转到这个状态的时候将被调用。
changeUrl 布尔类型或者字符串 布尔类型指示是否为当前状态创建一个唯一的hash值 如果是一个字符串,那么将使用这个字符串而不是hash值。
- var state = {
- back: function() { alert("Back was clicked!");
- dojo.back.addToHistory(repeatState); },
- forward: function() { alert("Forward was clicked!"); }
- };
dojo 的back对象将会在用户点击浏览器后退按钮的时候自动将当前state从historyStack中Pop出来。同时进入到前一个state。
下面摘选自dojo库的back.js
- function handleBackButton(){
- //summary: private method. Do not call this directly.
- //The "current" page is always at the top of the history stack.
- //console.debug("handlingBackButton");
- var current = historyStack.pop();
- if(!current){ return; }
- var last = historyStack[historyStack.length-1];
- if(!last && historyStack.length == 0){
- last = initialState;
- }
- if(last){
- if(last.kwArgs["back"]){
- last.kwArgs["back"]();
- }else if(last.kwArgs["backButton"]){
- last.kwArgs["backButton"]();
- }else if(last.kwArgs["handle"]){
- last.kwArgs.handle("back");
- }
- }
- forwardStack.push(current);
- //console.debug("done handling back");
- }
完整的例子,请看dojo1.0的发行包里面的back.html(dojo/tests/back.html),里面有完成的例子。
dojo怎么控制到后退按钮的呢?怎么记录书签,其中的奥妙何在呢?那就要看iframe在这里起到什么作用了。
2. 利用iframe 了控制每个页面的书签(bookmark)
在页面地址没有变化的情况下,怎么记录书签呢?怎么样让用户能够收藏呢?如果要能够收藏,地址一定要变化,但是地址变化的时候又要确保页面的内容不发生变化。How to do?
Yes, Use # , 增加书签到地址后面,如: http://yourdomain/yourpage#bookmark 这样的话,地址栏变化了,那么后退按钮也就有了历史记录了。别高兴的太早,Ie并不是这样。Ie并不会将http://yourdomain/yourpage#bookmark和http://yourdomain/yourpage认为是两个页面,所以也就不会加入到History中,怎么处理这个问题呢?iframe在这里派上作用拉。通过设置iframe的src属性可以让Ie将这些状态记录到history中。
http://codinginparadise.org/weblog/2005/09/ajax-history-libraries.html
评论
RSH似乎对AJAX的历史记录解决的不错,并且是一个很轻量级的独立的框架
www.dojotoolkit.com
[url=http://www.gwteasy.cn][/url]小蜗牛娱乐平台
javascript 写的相信吗?纯的ajax有bug吗?
好好的EXT被弄得又卡又难看
[url=http://www.gwteasy.cn][/url]小蜗牛娱乐平台
javascript 写的相信吗?纯的ajax有bug吗?
它的io进行了统一封装,使用bind接口通讯,并进行了排队。这样的封装也就支持了它通过iframe来模拟前进后退,非常方便。
这一点它比Prototype和JQuery这样的轻封装占有了一些优势,也方便你扩展一些Js上的AOP机制上去。
但是它还有不适用场合:使用iframe通讯的场合(如跨子域),或者scriptio的时候,不能用history。
<p>最初的web程序只是一些静态的网页,一般都通过地址栏的URL地址来进行定位,所以,浏览器集成了很方便的History功能,让你在浏览的历史记录中来回切换。可是,随着复杂应用程序开始越来越多的通过浏览器来作为客户端,噩梦就开始了。</p>
<p>近年来,Ajax技术的兴起为程序设计者和客户提供了不同的技术实现和用户体验,Ajax火了起来,也开始颠覆了传统的web操作和应用传统。但是浏览器并没有相应的来迎合这些变化,这样的话, Ajax 程序也同样的面临浏览器的干扰,而History功能就是其中让人头疼的一个。</p>
<p>越来越多的程序员面临这个问题,开始考虑解决之道,解决的方案五花八门,不过都这能解决问题的一部分,无法从根本上解决这个问题。要根本解决这个问题,只怕需要浏览器的厂商和标准部门针对Ajax一起来想出一个标准化的处理方式。</p>
<p>当然我们没有时间来等待别人来帮助我们解决问题,我这里介绍一下Dojo 解决这个问题的方法,同时研究一下它的实现原理。</p>
<h4>需要解决的问题</h4>
<p>Ajax程序进行页面内容变化的时候,并没有刷新整个页面也没有改变浏览器地址,所以如果进行以下的操作将会出现无法意料的问题:</p>
<p>行为案例:1<strong>search 页面</strong>--2<span style='color: #ff0000;'>search</span>-->3显示列表在本页面--4<span style='color: #ff0000;'>点击列表中的某条记录</span>--5页面切换-->6<strong>所选记录的详细内容页面</strong>-->7<span style='color: #ff0000;'>编辑并保存</span>-->8停留在原页面,提示保存成功-->9<span style='color: #ff0000;'>返回</span>--.10页面切换-->11<strong>search页面</strong></p>
<p><strong>上面的步骤都不会导致浏览器地址变化,因为我们的应用是单页面的frame。</strong></p>
<p>这个案例涉及到两个页面(<strong>黑体 1,6</strong>),4 个动作(<span style='color: #ff0000;'>红色 2,4,7,9</span>)</p>
<p>后退/ 前进: 如果在step6的时候,如果浏览器的后退按钮可以点击的话(一般如果你之前没有访问过别的url,那么将不会有后退地址),将不会回到3或者1,而是1之前你访问过的地址。</p>
<p>刷新:如果在step6的时候,你点击刷新,将不会刷新step6所在的页面,因为浏览器的地址没有发生变化,你会发现,页面刷新之后来到了step1.</p>
<p>收藏: 同上,你收藏的step1所在的页面。</p>
<p>客户看到他花钱买的程序却是这样的行为,客户岂不是要疯掉!!!</p>
<h4>解决之道</h4>
<p>1. dojo</p>
<span><span><span><span><span><span><span><span><span><span><span><span><span><span><span>
<p> dojo1.0 提供dojo.back 对象来处理这里问题,可以记录页面状态到一个堆栈对象(<span style='font-family: Arial;'>historyStack</span>)中。但是这个<span style='font-family: Arial;'>historyStack开始是空的,当我们进入的首页的时候,可以通过<span style='font-family: Arial;'>setInitialState 方法设置他的第一个状态,如 </span></span><span style='font-family: Arial;'/></p>
<div class='code_title'>js 代码</div>
<div class='dp-highlighter'>
<ol class='dp-c'>
<li class='alt'><span><span>dojo.back.setInitialState(currentState); </span></span> </li>
</ol>
</div>
<p>之后每一次页面状态变化,你都可以将这个状态用书签记录下来,如</p>
<div class='code_title'>js 代码</div>
<div class='dp-highlighter'>
<ol class='dp-c'>
<li class='alt'><span><span>dojo.back.addToHistor(currentState); </span></span> </li>
</ol>
</div>
<p>state 代表你需要记录的页面状态,一般包括下面几个属性:</p>
<p><span style='font-family: Arial;'>back 函数 //当用户点击后退按钮,并且跳转到这个状态的时候将被调用。<br/>
forward 函数 // 当用户点击前进按钮,并且跳转到这个状态的时候将被调用。<br/>
changeUrl 布尔类型或者字符串 布尔类型指示是否为当前状态创建一个唯一的hash值 如果是一个字符串,那么将使用这个字符串而不是hash值。</span> </p>
<div class='dp-highlighter'>
<ol class='dp-c'>
<li class='alt'><span><span class='keyword'>var</span><span> state = { </span></span> </li>
<li><span> back: </span><span class='keyword'>function</span><span>() { alert(</span><span class='string'>"Back was clicked!"</span><span>); </span> </li>
<li><span> dojo.back.addToHistory(repeatState); }, </span> </li>
<li class='alt'><span> forward: </span><span class='keyword'>function</span><span>() { alert(</span><span class='string'>"Forward was clicked!"</span><span>); } </span> </li>
<li><span> }; </span> </li>
</ol>
</div>
<p>dojo 的back对象将会在用户点击浏览器后退按钮的时候自动将当前state从<span style='font-family: Arial;'>historyStack中Pop出来。同时进入到前一个state。</span></p>
<p>下面摘选自dojo库的back.js</p>
<div class='code_title'>js 代码</div>
<div class='dp-highlighter'>
<ol class='dp-c'>
<li class='alt'><span><span class='keyword'>function</span><span> handleBackButton(){ </span></span> </li>
<li><span> </span><span class='comment'>//summary: private method. Do not call this directly. </span><span> </span> </li>
<li class='alt'><span> </span> </li>
<li><span> </span><span class='comment'>//The "current" page is always at the top of the history stack. </span><span> </span> </li>
<li class='alt'><span> </span><span class='comment'>//console.debug("handlingBackButton"); </span><span> </span> </li>
<li><span> </span><span class='keyword'>var</span><span> current = historyStack.pop(); </span> </li>
<li class='alt'><span> </span><span class='keyword'>if</span><span>(!current){ </span><span class='keyword'>return</span><span>; } </span> </li>
<li><span> </span><span class='keyword'>var</span><span> last = historyStack[historyStack.length-1]; </span> </li>
<li class='alt'><span> </span><span class='keyword'>if</span><span>(!last && historyStack.length == 0){ </span> </li>
<li><span> last = initialState; </span> </li>
<li class='alt'><span> } </span> </li>
<li><span> </span><span class='keyword'>if</span><span>(last){ </span> </li>
<li class='alt'><span> </span><span class='keyword'>if</span><span>(last.kwArgs[</span><span class='string'>"back"</span><span>]){ </span> </li>
<li><span> last.kwArgs[</span><span class='string'>"back"</span><span>](); </span> </li>
<li class='alt'><span> }</span><span class='keyword'>else</span><span> </span><span class='keyword'>if</span><span>(last.kwArgs[</span><span class='string'>"backButton"</span><span>]){ </span> </li>
<li><span> last.kwArgs[</span><span class='string'>"backButton"</span><span>](); </span> </li>
<li class='alt'><span> }</span><span class='keyword'>else</span><span> </span><span class='keyword'>if</span><span>(last.kwArgs[</span><span class='string'>"handle"</span><span>]){ </span> </li>
<li><span> last.kwArgs.handle(</span><span class='string'>"back"</span><span>); </span> </li>
<li class='alt'><span> } </span> </li>
<li><span> } </span> </li>
<li class='alt'><span> forwardStack.push(current); </span> </li>
<li><span> </span><span class='comment'>//console.debug("done handling back"); </span><span> </span> </li>
<li class='alt'><span> } </span> </li>
</ol>
</div>
<p>完整的例子,请看dojo1.0的发行包里面的back.html(<span style='font-family: Arial;'>dojo/tests/back.html</span>),里面有完成的例子。</p>
<p> </p>
<p>dojo怎么控制到后退按钮的呢?怎么记录书签,其中的奥妙何在呢?那就要看iframe在这里起到什么作用了。</p>
<p> </p>
<p>2. 利用iframe 了控制每个页面的书签(<span style='font-family: Arial;'>bookmark</span>)</p>
<p> 在页面地址没有变化的情况下,怎么记录书签呢?怎么样让用户能够收藏呢?如果要能够收藏,地址一定要变化,但是地址变化的时候又要确保页面的内容不发生变化。How to do? </p>
<p>Yes, Use # , 增加书签到地址后面,如: <a href='http://yourdomain/yourpage#bookmark'>http://yourdomain/yourpage#bookmark</a> 这样的话,地址栏变化了,那么后退按钮也就有了历史记录了。别高兴的太早,Ie并不是这样。Ie并不会将<a href='http://yourdomain/yourpage#bookmark'>http://yourdomain/yourpage#bookmark</a>和<a href='http://yourdomain/yourpage'>http://yourdomain/yourpage</a>认为是两个页面,所以也就不会加入到History中,怎么处理这个问题呢?iframe在这里派上作用拉。通过设置iframe的src属性可以让Ie将这些状态记录到history中。</p>
<p> </p>
<p>参考:<span style='font-family: Arial;'><a href='http://www.contentwithstyle.co.uk/Articles/38/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps'>http://www.contentwithstyle.co.uk/Articles/38/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps</a></span></p>
<p> <span style='font-family: Arial;'>http://codinginparadise.org/weblog/2005/09/ajax-history-libraries.html</span></p>
<div class='code_title'>js 代码</div>
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></div>
发表评论
-
JQuery 文件上传收集
2009-08-14 12:25 14554http://www.webjx.com/javascript ... -
js 判断session过期,并注销
2009-07-14 15:38 12633客户希望如果没有操作,在30分钟后session过期,并且自动 ... -
Dojo 客户端性能优化
2008-06-05 12:05 5314Dojo 客户端调优的方式: 1. 编译合适的dojo文件。 ... -
使用Dojo的痛苦经历
2008-05-21 00:23 124802007年6月项目准备开始了,刚来到一个新的项目组,什么都是新 ... -
体验dojo强大的grid控件——简单示例剖析
2007-12-11 15:38 12198Dojo 从 v1.0 开始引入了一个功能强大,快速,健壮的控 ... -
开始学习和使用Dojo
2007-12-07 14:38 96dojo现在最新的发行版本是1.0.1. 这个版本跟0.43的 ... -
Dojo, 从0.43 向1.0 迁移(二)widget 变化列表
2007-12-07 11:49 1972widget change list ... -
Dojo, 从0.43 向1.0 迁移(一)
2007-12-07 10:47 1661公司的项目4月份开始,我们选择了dojo,不为别的,因为他 ... -
用 javascript 处理 JSON
2007-11-07 11:07 72595因为JSON 是 javascript 的一个子集,所 ... -
JSON简介
2007-02-06 15:37 2125JSON (JavaScript Object Notatio ... -
JSON-RPC的简介
2007-02-06 13:28 2307JSON-RPC协议是一种远程过程调用协议,其设计的目 ...
相关推荐
17. **模块化开发**:通过AMD(异步模块定义)或CommonJS等方式,组织和管理复杂的Ajax应用程序。 18. **Ajax与WebSocket**:WebSocket提供了双向通信,适用于实时应用,如在线游戏和实时股票报价。 19. **响应式...
程序描述:本章将介绍 GWT应用中高级应用的部分,包括各中组件和布局、如何发送XMLHttpRequest请求,以及如何解决浏览器历史记录问题等等,同时读者还将详细的了解RPC应用的开发过程。 /xmlsample/AjaxSample....
随着互联网技术的发展,尤其是Web2.0时代和AJAX技术的兴起,JavaScript迅速成为主流的Web前端编程语言。 JavaScript的发展历史中,其类库和框架的发展尤为引人注目。众多框架如jQuery、 dojo、 ExtJs、 Prototype等...