目前只實現了hash,整個思路是,咱們有一個主文件Router.js,這個文件中咱們定義了兩大方法,use和routejavascript
use的做用是將全部的中間件全push到Router的middleware數組裏面。route方法裏面,咱們調用了this._matcher的addRoutes方法。this._matcher實際上是createMatcher的實例。html
route(path, controller){
// 在執行controller以前, 先執行全部的中間件
// 將全部routes及其controller添加進_matcher
this._matcher.addRoutes(path, (req) => {
this._middlewares.forEach(fn => {
fn(req)
});
/** * res(response)實際是Router: this * callback(req, res) */
console.log("傳進來了......")
controller&&controller(req, this)
})
}
複製代碼
createMatcher的做用是將配置文件的全部路由規則正則,而且解析咱們每一次請求的url。它的match方法就是用於解析這個url。可是match方法是在HashHistory裏面調用的。由於咱們的Router 實例化的時候,傳給了它。並將實例化的賦值給this._history前端
this._history = this._mode === 'hash'
? new HashHistory({matcher: this._matcher})
: new Html5History({matcher: this._matcher});
複製代碼
addRoutes接收一個path和一個handler,handler其實就是 路由配置文件裏面的全部中間件,以及app.route(path, controller)裏每一個路由對應的controller。path被正則化,用於咱們的app頁面匹配每一個url,push到createMatcher的_routes裏。vue
_toReg是將route(path, controller)的path正則化。java
addRoutes(path, handler){
let routeReg = this._toReg({
path: path,
handler: handler,
params: []
});
this._routes.push(routeReg);
}
複製代碼
咱們怎麼樣去截獲一個請求呢?實際上用截獲這個詞,並不十分準確。在HashHistory裏面,咱們經過_setListener,實現對hash變化的監聽。git
_setListener(){
window.addEventListener('load', this._refresh);
window.addEventListener('hashchange', this._refresh);
}
複製代碼
當咱們要從頁面a到達頁面b的時候,是經過點擊頁面a上面的鏈接,這個連接有一個onclick事件,go裏面的參數就是咱們的請求url。github
<li onclick="app.go('/order/fruit?price=100&time=now', {message: '訂單'})">訂單</li>
複製代碼
當咱們點擊它的時候,實際是咱們先修改window.location.hash這個值(點擊事件先觸發了go方法)。this._cache[url] = body,存儲了咱們想要傳入的信息。好比獲取當前form表格的值。vue-router
go(url, body){
this._cache[url] = body;
console.log("come here........")
window.location.hash = `${url}`;
}
//..................................//
_getHash (){
// 參考Vue-router
// window.location.hash不穩定, Firefox會發布新版本
const href = window.location.href;
const index = href.indexOf('#');
return index === -1 ? '' : href.slice(index + 1)
}
複製代碼
一旦hash被修改,咱們的onhashchange事件就能監聽到,而後觸發_refresh方法,_refresh裏面調用_getHash,獲取這個hash值,而後調用傳參進來的createMatcher的match方法,解析這個path(實際就是上面提到的url);解析完以後返回一個matchedRoutes,這個matchedRoutes不只包含解析完的param,還包括這個route對應的handler(handler包括中間件和路由對應的controller)。數組
this._refresh = () => {
// 每次hash變化, 獲取變化後的hash
console.log("refesh啦!............")
const path = this._getHash();
const matchedRoutes = this.matcher.match(path);
this._matchedCount = matchedRoutes.length;
this._fireHandlers(matchedRoutes, this._cache[path]);
}
複製代碼
_fireHandlers是最終call handler,而且處理請求的最終函數。app
_fireHandlers(matchedRoutes, body) {
console.log("I am the best one")
for (let i = 0; i < matchedRoutes.length; i++) {
// 匹配到的路由包含有待執行的controller
const item = matchedRoutes[i];
// 構造請求體
const request = {
body: body || {},
query: item.query,
params: item.params
};
def(request, 'route', item.path);
def(request, 'url', item.url);
item.handler(request)
}
}
複製代碼
從他的代碼中, 學習到了不少, 對Vue-router的理解也加深了更多!