SPA的成功離開不這三個東西,分層架構,路由系統,儲存系統。分層架構是咱們組織複雜代碼的關鍵,這裏特指MVVM的avalon;路由系統是將多個頁面壓縮在一個頁面的關鍵;儲存系統特指本地儲存,是安全保存大量數據的關鍵。本章節介紹的是avalon三柱臣之一的mmRouter(內含mmHistory)。javascript
咱們先上一個示例吧。html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>路由系統</title> <script src="avalon.js"></script> <script> require(["mmRouter"], function() { var model = avalon.define({ $id: "test", currPath: "", params: {}, query: {}, args: "[]" }) function callback() { model.currPath = this.path var params = this.params if ("time" in params) { params.time = avalon.filters.date(params.time, "yyyy年M月dd日") } model.params = params model.args = "[" + [].slice.call(arguments).join(",") + "]" model.query = this.query } avalon.router.get("/aaa/", callback) avalon.router.get("/bbb", callback) avalon.router.get("/ccc/:ccc", callback) avalon.router.get("/ddd/{time:date}/", callback) avalon.router.get("/eee/{count:\\d{4}}/", callback) avalon.router.get("/fff", callback) avalon.history.start({ basepath: "/avalon" }) avalon.scan() }) </script> </head> <body > <div ms-controller="test"> <table width="100%" height="300"> <tr> <td width="250"> <ul> <li><a href="#!/aaa">aaa</a></li> <li><a href="#!/bbb?uu=3445345&were=4324">bbb</a></li> <li><a href="#!/ccc/etretr">ccc</a></li> <li><a href="#!/ddd/2014-09-19">ddd</a></li> <li><a href="#!/eee/2222">eee</a></li> <li><a href="#!/fff?a=1&nn=4&dfg=676">fff</a></li> </ul> </td> <td> <div style="color:red">this.path: {{currPath}}</div> <div style="color:blue">arguments: {{args}}</div> <fieldset> <legend>this.params</legend> <ol> <li ms-repeat="params"> {{$key}}: {{$val}}</li> </ol> </fieldset> <fieldset> <legend>this.query</legend> <ol> <li ms-repeat="query"> {{$key}}: {{$val}}</li> </ol> </fieldset> </td> </tr> </table> <div style="height: 600px;width:1px;"> </div> <p id="eee">會定位到這裏</p> </div> </body> </html>
眼見爲實,能夠看到mmRouter很好地在IE6下運行,對於高版本的瀏覽器更不在話下。回退按鈕,hash若是與頁面上的某個錨記同名,它也會自動定拉到那裏去。html5
咱們接着詳細介紹一下它的用法吧。java
mmHistory是用於歷史管理,它會劫持頁面上全部點擊連接的行爲,當這些連接是以#/ 、#!/開頭,就嘗試匹配路由規則,阻止頁面刷新(經過hash方式或HTML5的replaceState方式)。mmRouter是給咱們定義路由規則,路由規則能夠更精細地指定每一個參數(param)的匹配規則,若是符合就執行對應的回調,若是不符合,就進入error回調。git
當用戶點擊頁面連接時,路址欄會發生變化,avalon是參考了angular的方式來處理路址欄。 github
當咱們使用history API mode的時候,咱們對於不一樣的瀏覽器,須要不一樣的連接, 但咱們只須要提供其hash部分就好了,例如<a href=「#/aaa」>link</a>web
當用戶單擊這個超連接時:ajax
你會發現,Hashbang mode中的#!後面的部分等於HTML5 mode中的除域名外的全部部分。而#!實際上是google的 _escaped_fragment_ 爬抓規則, 方便咱們的AJAX應用也能被爬蟲收錄。固然,咱們還須要在head標籤內添加一個meta標籤:chrome
<meta name="fragment" content="!" />
想了解更多關於這個技術的信息,能夠查看這裏 下面是路由器的API列表:express
最後咱們再詳細介紹一下路由規則,它是一個字符串,必須以/開頭,它能夠在每一個/後直接接冒號,表示這以後到下一個斜線或末尾是一個參數。它也可使用花括號表示裏面的內容也一個參數。斜錢風格是來自backbone與express的,花括號風格是來自ui-router。花括號風格更爲強大些,所以它能夠指定更詳細的匹配規則。
avalon.router.get("/ddd/:dddID/",callback) avalon.router.get("/ddd/{dddID}/",callback) avalon.router.get("/ddd/{dddID:[0-9]{4}}/",callback) avalon.router.get("/ddd/{dddID:int}/",callback)
mmRouter默認有四個參數匹配器,分別叫作date, init, bool, string。
$types: { date: { pattern: "[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])", decode: function(val) { return new Date(val.replace(/\-/g,"/")) } }, string: { pattern: "[^\/]*" }, bool: { decode: function(val) { return parseInt(val, 10) === 0 ? false : true; }, pattern: "0|1" }, int: { decode: function(val) { return parseInt(val, 10); }, pattern: "\d+" } }
decode方法是用來將咱們從地址欄抽取出來的那些小字符串轉換爲想要的類型或格式。若是你想要更多效果,還能夠本身添加,如avalon.router.$type.d4 = { pattern: ’[0-9]{4}’, decode: Number}
avalon.router.get("/ddd/{dddID:d4}/",callback)
總而言之,mmRouter是遠遠比angular自帶路由器與backbone那個強大N多。將來還會進一步開發相似ui-router那樣基於狀態管理的路由器,敬請期待!