前端神器avalonJS入門(三)

本章將介紹如何使用avalon來實現前端路由功能。javascript

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

關於該路由系統更具體的描述,能夠查閱這裏html

做爲示例,咱們打算製做一個網站的 「用戶中心」 頁面,其中左側爲導航列表,右側爲受左側列表控制的內容顯示區域:前端

該「用戶中心」頁面有這麼幾個要求:java

⑴ 頁面不跳轉,僅作局部(即內容區域部分)刷新;jquery

⑵ 能夠經過不一樣的url進入對應的頁面(即內容區域顯示對應的內容);git

⑶ 瀏覽器能記住url狀態,好比從「帳戶詳情」點入「我要充值」頁面,而後再點擊瀏覽器返回按鈕,能夠正確回到「帳戶詳情」頁面。github

因爲不是石器時代,天然不會再選擇iframe這種內耗高、不友好的元素來架構頁面(並且iframe也實現不了後面兩個需求呀)。那麼咱們會很快聯想到Ajax技術,這個想法很本質,不過單純的Ajax也沒辦法達到咱們的要求,因此才須要引入開頭提到的兩個avalon路由模塊。後端

咱們能夠先寫出簡單的頁面原型:瀏覽器

index.html:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>帳戶中心</title>
    <link rel="stylesheet" href="css/user.css">
    <script src="js/lib/require.js" type="text/javascript" data-main="js/page/user"></script>
</head>
<body ms-controller="user" class="ms-controller">
<script type="text/javascript">
    //這裏給後端提供數據接口
    var conf = {
        username: {"id": "11", "name": "VaJoy"}
    }
</script>
<header>
    <span>{{username.name}}你好,歡迎來到帳戶中心</span>
</header>
<nav>
    <ul>
        <li><a href="#!/index">個人首頁</a></li>
        <li><a href="#!/detail">帳戶詳情</a></li>
        <li><a href="#!/recharge">我要充值</a></li>
    </ul>
</nav>
<article>
    內容...
</article>
</body>
</html>

user.js:

require.config({
    baseUrl: 'js/lib/', 
    paths:{   
        avalon: 'avalon',
        domReady:'domReady',
        mmHistory: 'mmHistory',
        mmRouter: 'mmRouter',
        jquery: 'jq'
    },
    shim:{
        avalon: { exports: "avalon" },
        mmHistory:{ deps: ['avalon']},
        mmRouter:{ deps: ['avalon']}
    }
});

require(['avalon',"domReady!"], function() {
    var vm = avalon.define({
        $id: "user",
        username:conf.username
    });
    avalon.scan();
});

user.css:

body,html{padding: 0;margin:0;background: #EEE;}
.ms-controller{visibility: hidden;}
header{height: 50px;background: white;}
header>span{display:block;padding: 16px;}
nav{position: absolute;left:0;margin-top:50px;width: 200px;}
nav>ul>li{margin-top: 12px;}
nav>ul>li>a{text-decoration: none;color:blue;}
nav>ul>li>a:hover{color:red;}
article{padding: 15px;margin-left:200px;min-height: 600px;background: white;}

運行結果以下:

接着咱們要新建三個頁面——mine.html、detail.html 和 recharge.html ,分別對應「個人首頁」、「帳戶詳情」 和 「我要充值」 的右側內容,咱在裏面隨便寫點內容意思意思便可,好比mine.html我就寫了一句話:

接着咱們默認先把mine.html引入到index.html中,這裏咱們藉助avalon的 ms-include-src 接口,修改下index.html:

<nav>
    <ul>
        <li><a href="#!/index">個人首頁</a></li>
        <li><a href="#!/detail">帳戶詳情</a></li>
        <li><a href="#!/recharge">我要充值</a></li>
    </ul>
</nav>
<article ms-include-src="pageUrl"> <!--這裏使用ms-include-src接口,它會引入pageUrl屬性所對應的文件-->
</article>

接着修改 user.js的部分:

require(['avalon',"domReady!"], function() {
    var vm = avalon.define({
        $id: "user",
        username:conf.username,
        pageUrl:"mine.html"  //默認爲mine.html
    });
    avalon.scan();
});

運行以下:

接着是時候讓 mmHistory.js 和 mmRouter.js 發揮它們的做用了,咱們修改下user.js的部分代碼:

require(['mmHistory','mmRouter',"domReady!"], function() {
    var vm = avalon.define({
        $id: "user",
        username:conf.username,
        pageUrl:"mine.html"  //默認爲mine.html
    });
    function callback() {
        if(this.path==="/index"){
            vm.pageUrl="mine.html";
        }else {
            var path_tail = this.path.replace(/\//, "");
            vm.pageUrl = path_tail + ".html";  //動態修改pageUrl屬性值
        }
    }
    avalon.router.get("/*path", callback); //劫持url hash並觸發回調
    avalon.history.start(); //歷史記錄堆棧管理
    avalon.scan();
});

注意因爲在 require.config 的 shim 中咱們已經定義了 mmHistory.js 和 mmRouter.js 是依賴於avalon的,故此處無須再引入avalon模塊,requireJS執行該代碼段以前會先加載好avalon的。

咱們經過這兩行代碼執行了路由和歷史記錄的管理:

    avalon.router.get("/*path", callback); //劫持url hash並觸發回調
    avalon.history.start(); //歷史記錄堆棧管理

其中router.get() 的第一個參數表示路由匹配規則,好比這裏的「/*path」表示匹配所有路徑,匹配到了就觸發回調callback函數。

更多的匹配規則咱們能夠直接在  mmRouter.js 中查看註釋信息:

router.get() 在觸發callback前會生成一個this.path屬性供callback調用(你也能夠給回調函數定義一個參數,其默認值等同與path),其值爲當前匹配到的路徑,好比當url後綴變成 #!/recharge 的時候,this.path的值爲匹配到的"/recharge" 。瞭解了這個以後,callback 函數也很好理解了:

    function callback() {
        if(this.path==="/index"){
            vm.pageUrl="mine.html"; //若是url後綴變成"#!/index",則pageUrl爲「mine.html」
        }else {
            var path_tail = this.path.replace(/\//, ""); //去掉this.path值的第一個斜槓
            vm.pageUrl = path_tail + ".html";  //動態修改pageUrl屬性值
        }
    }

這時候的運行結果以下所示:

自此便實現了咱們的需求。可是這樣還不夠完美——每一個頁面的樣式咋處理呢?

咱們能夠直接在頁面上寫<style>標籤,或者直接寫個<link>引入外部樣式文件,但前者很差維護,後者畢竟不是插入到head中的不太規範。那麼咱們可否也用requireJS模塊化動態引入樣式文件呢?答案是確定的,不過得藉助於其組件css.js

以「帳戶詳情」(detail.html)爲例,咱們建立一個detail.css文件,裏面設置 .detail{color:red;}。

先確保require.config中的paths里加上了該組件:

    paths:{   //這裏配置的地址,都是相對於上方的baseUrl的
        avalon: 'avalon',
        domReady:'domReady',
        mmHistory: 'mmHistory',
        mmRouter: 'mmRouter',
        css: 'css'  //加上css.js
    }

而後修改detail.html頁面內容:

<section ms-controller="detail" class="detail ms-controller">
    喲喲喲,這裏是詳情頁面,{{username.name}}你好
</section>
<script>
    require(['avalon','css!../../css/detail.css'], function(){
    //下面的其實建議寫成一個模塊detail.js而後由require引入
        avalon.define({
            $id: "detail",
            username: conf.username
        });
        avalon.scan();
    })
</script>

「css!/XXX.css」 是css.js的寫法,注意以"css!"開頭便可。

運行結果以下:

以上即是avalon前端路由的簡單實現,本章的示例代碼能夠從這裏下載。

後續章節可能會開始寫一寫avalon的API。共勉~

donate

相關文章
相關標籤/搜索