本章將介紹如何使用avalon來實現前端路由功能。javascript
咱們須要用到兩個avalon路由配套模塊—— mmHistory.js 和 mmRouter.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。共勉~