在學習 vue-router 的代碼之前,先來簡單了解一下前端路由。
前端路由主要有兩種實現(xiàn)方法:
先來看看這兩種方法的實現(xiàn)原理。
接著我們將用它們來簡單實現(xiàn)一個自己的前端路由。
前端路由
Hash 路由
url 的 hash
是以 #
開頭,原本是用來作為錨點,從而定位到頁面的特定區(qū)域。當 hash
改變時,頁面不會因此刷新,瀏覽器也不會向服務器發(fā)送請求。
http://www.xxx.com/#/home
同時, hash
改變時,并會觸發(fā)相應的 hashchange
事件。所以,hash 很適合被用來做前端路由。當 hash 路由發(fā)生了跳轉,便會觸發(fā) hashchange 回調,回調里可以實現(xiàn)頁面更新的操作,從而達到跳轉頁面的效果。
window.addEventListener('hashchange', function () { console.log('render'); });
History 路由
HTML5 規(guī)范中提供了 history.pushState
和 history.replaceState
來進行路由控制。通過這兩個方法,可以實現(xiàn)改變 url 且不向服務器發(fā)送請求。同時不會像 hash
有一個 #
,更加的美觀。但是 History 路由需要服務器的支持,并且需將所有的路由重定向到根頁面。
History 路由的改變不會去觸發(fā)某個事件,所以我們需要去考慮如何觸發(fā)路由更新后的回調。
有以下兩種方式會改變 url:
第一個方式可以封裝一個方法,在調用 pushState(replaceState)后再調用回調。
function push (url) { window.history.pushState({}, null, url); handleHref(); } function handleHref () { console.log('render'); }
第二個方式,瀏覽器的前進與后退會觸發(fā) popstate
事件。
window.addEventListener('popstate', handleHref);
路由實現(xiàn)
我們通過 <a>
標簽來進行切換路由,通過一個 <div>
標簽來裝載各路由對應的頁面內容。
參考 vue-router 的調用,我們會這么地調用一個 Router
,將路由與對應組件作為參數(shù)傳入:
const router = new Router([ { path: '/', component: 'home' }, { path: '/book', component: 'book' }, { path: '/movie', component: 'movie' } ]);
數(shù)組里是各路由對應的要顯示的內容,接下來就來開始實現(xiàn)這個 Router
。
Hash 路由實現(xiàn)
Hash 路由 <a>
標簽都需要帶上 #
:
<div> <a href="#/" rel="external nofollow" >home</a> <a href="#/book" rel="external nofollow" >book</a> <a href="#/movie" rel="external nofollow" >movie</a> <div id="content"></div> </div>
Router
的代碼實現(xiàn)如下:
class Router { constructor (options) { this.routes = {}; this.init(); // 遍歷,綁定視圖更新 options.forEach(item => { this.route(item.path, () => { document.getElementById('content').innerHTML = item.component; }); }); } // 綁定監(jiān)聽事件 init () { window.addEventListener('load', this.updateView.bind(this), false); window.addEventListener('hashchange', this.updateView.bind(this), false); } // 更新試圖 updateView () { const currentUrl = window.location.hash.slice(1) || '/'; this.routes[currentUrl] && this.routes[currentUrl](); } // 將路由與回調函數(shù)關聯(lián) route (path, cb) { this.routes[path] = cb; } }
實現(xiàn)效果如下:
History 路由實現(xiàn)
History 路由需要服務器的支持,可以點擊這里 的代碼參考。
<div> <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/" rel="external nofollow" >home</a> <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/book" rel="external nofollow" >book</a> <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/movie" rel="external nofollow" >movie</a> <div id="content"></div> </div>
Router
的代碼實現(xiàn)如下:
class Router { constructor (options) { this.routes = {}; this.init(); this.bindEvent(); // 遍歷,綁定視圖更新 options.forEach(item => { this.route(item.path, () => { document.getElementById('content').innerHTML = item.component; }); }); } // 綁定點擊事件 bindEvent () { const _this = this; const links = document.getElementsByTagName('a'); [].forEach.call(links, link => { link.addEventListener('click', function () { const url = this.getAttribute('data-href'); _this.push(url); }); }); } // 綁定監(jiān)聽事件 init () { window.addEventListener('load', this.updateView.bind(this), false); window.addEventListener('popstate', this.updateView.bind(this), false); } push (url) { window.history.pushState({}, null, url); this.updateView(); } // 更新試圖 updateView () { const currentUrl = window.location.pathname || '/'; this.routes[currentUrl] && this.routes[currentUrl](); } // 將路由與回調函數(shù)關聯(lián) route (path, cb) { this.routes[path] = cb; } }
實現(xiàn)效果如下:
最后
前端路由實現(xiàn)方式有兩種,分別是:
原理都是修改 url 的同時不刷新頁面,不向服務器發(fā)送請求,通過監(jiān)聽特殊的事件來更新頁面。
以上實現(xiàn)全部源碼參考這里。
聲明:本網(wǎng)頁內容旨在傳播知識,若有侵權等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com