迷你MVVM框架 avalonjs 學習教程20、路由系統

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>

enter image description here

眼見爲實,能夠看到mmRouter很好地在IE6下運行,對於高版本的瀏覽器更不在話下。回退按鈕,hash若是與頁面上的某個錨記同名,它也會自動定拉到那裏去。html5

咱們接着詳細介紹一下它的用法吧。java

  1. 先引入mmRouter(請將mmRouter.jsmmHistory.js這兩個文件與avalon.js放在一塊兒)
  2. 定義VM
  3. 定義路由規則
  4. 啓動歷史管理器
  5. 開始掃描

mmHistory是用於歷史管理,它會劫持頁面上全部點擊連接的行爲,當這些連接是以#/#!/開頭,就嘗試匹配路由規則,阻止頁面刷新(經過hash方式或HTML5的replaceState方式)。mmRouter是給咱們定義路由規則,路由規則能夠更精細地指定每一個參數(param)的匹配規則,若是符合就執行對應的回調,若是不符合,就進入error回調。git

當用戶點擊頁面連接時,路址欄會發生變化,avalon是參考了angular的方式來處理路址欄。 enter image description heregithub

  • Hashbang模式(默認), 這個模式下全部瀏覽器都支持
  • HTML5模式, 這個只能應用於firefox, chrome, safari,IE10+,若是瀏覽器不支持此特性,即便你設置avalon.history.start({html5Mode:true}),它也是在Hashbang模式下運行。

當咱們使用history API mode的時候,咱們對於不一樣的瀏覽器,須要不一樣的連接, 但咱們只須要提供其hash部分就好了,例如<a href=「#/aaa」>link</a>web

當用戶單擊這個超連接時:ajax

  • 在Hashbang mode中,URL會改成/index.html#!/aaa
  • 在HTML5 mode中,URL會改成/index.html/aaa

你會發現,Hashbang mode中的#!後面的部分等於HTML5 mode中的除域名外的全部部分。而#!實際上是google的 _escaped_fragment_ 爬抓規則, 方便咱們的AJAX應用也能被爬蟲收錄。固然,咱們還須要在head標籤內添加一個meta標籤:chrome

<meta name="fragment" content="!" />

想了解更多關於這個技術的信息,能夠查看這裏 下面是路由器的API列表:express

  • avalon.history.start(opts), 開始監聽URL變化,opts。enter image description here
  • avalon.history.stop(), 停止監聽URL變化。
  • avalon.router.get(path, callback),用於添加路由規則。第一個爲路由規則,如"/aaa", "/bbb/:bbbId","/eee/{eeeId}/ddd/{dddId:[0-9]{6}}" 冒號後的東西或花括號的東西表示爲參數,花括號模式下還能夠指定匹配規則。callback爲回調函數,框架會將冒號後的或花括中的匹配內容傳進來,此外this對象,包含了path、 params、 query等對象與屬性。
  • avalon.router.add(method, path, callback) , 添加回調,第一個爲請求類型,如GET,POST,DELETE什麼, 第2個爲路由規則,第3個爲回調函數
  • avalon.router.error(callback),若是沒有一條路由規則知足此請求,那麼就轉交此回調處理,咱們能夠在裏面寫跳轉到404頁面這樣的邏輯
  • avalon.router.navigate(path),強制觸發對應路徑的回調
  • avalon.router.setLastPath(path) , 這是框架本身調用,保存最近一次跳轉的路徑
  • *avalon.router.getLastPath() *,取得最近一次跳轉的路徑,好比用戶F5強制頁面,你在ready回調中執行此方法,獲得path,而後將它放進navigate中就能回到原來的頁面了。

最後咱們再詳細介紹一下路由規則,它是一個字符串,必須以/開頭,它能夠在每一個/後直接接冒號,表示這以後到下一個斜線或末尾是一個參數。它也可使用花括號表示裏面的內容也一個參數。斜錢風格是來自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那樣基於狀態管理的路由器,敬請期待!

相關文章
相關標籤/搜索