本文基于前一篇随笔处理页面前进回退多个状态还原的jQuery hashchange event扩展。
文章写的不太清楚,希望这篇补充的文档能帮助大家理解:点击这里
可能大家都没有看明白,前文给的那段代码到底能干什么。其实我自己也比较糊涂,最近工作比较忙,一直没有继续思考,今天回过头,修改了一下之前的代码,写了个完整的demo。还有些不完善的地方,不过基本上可以拿来用用了。
点这里下载Demo
压缩包里包含以下文件(JQuery库就不说了):
Test.html 演示页面
Scripts/jquery.ba-hashchange.js jquery hashchange 插件
Scripts/jquery.hashchangebroker.js 前一篇随笔的代码,修改了一些地方,下面会提到
Scripts/ui.statehashable.js 今天写的jquery widget,监控控件状态变更,更新hash,并订阅hash变更给控件
Scripts/base64.js 来源网上,base64编码解码库
Scripts/json2.js 来源网上,json序列化,反序列化库
关于之前的hashchangebroker,增加了对state值的base64编码处理。我希望用json来存储控件状态,所以用base64编码以便更新到url hash,应该有更好的做法,我这个只能算是懒办法:P。
ui.statehashable.js,代码如下:
1 (function ($) { 2 $.widget("ui.statehashable", { 3 _init: function () { 4 this.element.each(function () { 5 if (!this.id) return; 6 7 $(this).data("_hashstate", {}); 8 9 var self = $(this); 10 11 $.hashchangebroker.subscrib(this.id, function (fragData) { 12 var changedStates = {}; 13 var states = JSON.parse(fragData || "{}"); 14 15 var hashstates = self.data("_hashstate"); 16 17 var changed = false; 18 19 for (var key in states) { 20 if (!hashstates[key] && typeof (hashstates[key]) != "string" || hashstates[key] != states[key]) { 21 changedStates[key] = states[key]; 22 changed = true; 23 } 24 } 25 26 for (var key in hashstates) { 27 if (!states[key] && typeof (states[key] != "string")) { 28 changedStates[key] = ""; 29 changed = true; 30 } 31 } 32 33 self.data("_hashstate", states); 34 35 if (changed) 36 self.trigger("hashchange", [changedStates]); 37 }); 38 39 $(this).bind("statechange", function (e, name, state) { 40 self.data("_hashstate")[name] = state; 41 $.hashchangebroker.changeFrag(this.id, JSON.stringify(self.data("_hashstate"))); 42 }); 43 }); 44 } 45 }); 46 })(jQuery);
给dom对象增加了hashchange事件,如果hash中对应控件id的段发生变化,而且和控件当前状态不一致时,会触发此事件。同时bind了dom对象的statechange事件,接受控件的状态变化,并更新到url hash。
用法:$(dom对象).statehashable();
Test.html中写了一个叫testview的widget,点击testview中的按钮可以改变testview的几个state,同时可以反映到界面变化。同时,绑定hashchange事件以还原脚本状态。
触发statechange事件:
1 _changeText: function (stateName, state) { 2 $("." + stateName + "_text", this.element).text(state); 3 //触发statechange事件,以供ui.statehashable捕捉 4 this.element.trigger("statechange", [stateName, state]); 5 }, 绑定hashchagne事件,更新控件状态:
1 this.element.bind("hashchange", function (e, stateobj) { 2 for (var key in stateobj) { 3 switch (key) { 4 case "state1": 5 case "state2": 6 case "state3": 7 if (stateobj[key]) 8 $("." + key + "_text", self.element).text(stateobj[key]); 9 else 10 $("." + key + "_text", self.element).text("no state"); 11 break; 12 case "bgstate": 13 if (stateobj[key]) 14 self.element.css("background-color", stateobj[key]); 15 else 16 self.element.css("background-color", "#ffffff"); 17 break; 18 } 19 } 20 }); 21 }, 运行Test.html,点击按钮,可以改变控件状态,如果使用浏览器前进,后退按钮,可以看到界面会还原到相应的状态。如果刷新页面,也可以还原到hash对应的脚本运行状态。
写的比较乱,将就看吧,看demo应该可以看明白。基于statehashable应该可以做一些更有价值的的事情,个人感觉应该可以简化不少工作。