Vue-Router 源碼分析(三) VueRouter實例的屬性和方法


我們首先用new VueRouter()創建一個VueRouter實例,之后在創建根Vue實例時把這個VueRouter實例作為router屬性傳遞進去,在這個過程中一般有兩種方法可以獲取到該VueRouter的實例

第一種是node環境下,我們一般在項目源碼的路勁下創建一個router目錄,該目錄保存所有的路由配置信息,例如:

var router = new Router({
  routes: [/**/]
})
router.forEach((to,from,next)=>{
  next();
})
export default router;

這里我們創建new Router實例后可以直接對該實例進行操作,比如這里通過VueRouter實例設置了forEach導航守衛

還有一種獲取VueRouter實例的地方是在vue內,我們可以通過this.$router獲取到VueRouter實例:

this.$router.push('/login')

通過this.$router我們可以通過push、back等API進行路由跳轉。對於VueRouter實例來說它含有如下屬性和方法:

  • app          配置了router的Vue根實例
  • mode            當前的路由模式,可以為hash、history或者abstract
  • options         創建VueRouter實例時傳入的所有參數
  • history          當前的History對象(通過該對象進行路由跳轉的)
  • addRoutes   動態添加更多的路由規則,參數必須時一個符合routes選項要求的數組
  • push                      路由到新的路由地址
  • replace                 替換當前路由到新的路由(它不會向history添加新記錄)
  • go                         在history記錄中向前或向后退多少步
  • back                     在history記錄中后退一步,等效於go(-1)
  • forward                 在history記錄中前進一步,等效於go(1)
  • beforeEach                    全局前置守衛
  • beforeResolve              全局解析守衛
  • afterEach                      全局后置鈎子
  • onReady(callback,errorCallback)    注冊兩個回調函數,在路由完成初始導航時觸發
  • onError(callback)                  注冊一個回調,該回調會在導航過程中出錯時被調用

對於app屬性來說,我們經常用到的地方就是在導航首位里可以通過router.app.$store.tokens獲取當前是否有tokens,如果沒有,則路由到登錄頁面

在vue組件內可以通過this.$router.push()等進行路由跳轉,這些都是執行VueRouter實例的方法來實現的。

在Vue源碼內,VueRouter是一個函數對象,如下:

var VueRouter = function VueRouter (options) {      //構造函數
  if ( options === void 0 ) options = {};             //如果option為undefined,則修正為空對象

  this.app = null;
  this.apps = [];
  this.options = options;                             //保存options
  this.beforeHooks = [];                              //初始化三個數組,分別對應beforeEach、beforeResolve、afterEach三個全局導航守衛的注冊函數
  this.resolveHooks = [];
  this.afterHooks = [];
  this.matcher = createMatcher(options.routes || [], this);

  //初始化/修正mode
  var mode = options.mode || 'hash';
  this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false;
  if (this.fallback) {
    mode = 'hash';
  }
  if (!inBrowser) {
    mode = 'abstract';
  }
  this.mode = mode;

  switch (mode) {                                     //根據不同的模式,對this.history做出實例化
    case 'history':
      this.history = new HTML5History(this, options.base);
      break
    case 'hash':
      this.history = new HashHistory(this, options.base, this.fallback);
      break
    case 'abstract':
      this.history = new AbstractHistory(this, options.base);
      break
    default:
      {
        assert(false, ("invalid mode: " + mode));
      }
  }
};

其它的方法都是定義在VueRouter的原型對象上的,對於跳轉的接口來說(push、replace、go、back、forward)來說,它們是操作this.history對象來實現跳轉的。

vue初始化時會在beforeCreate生命周期函數內會執行VuerRouter實例的init方法,如下:

VueRouter.prototype.init = function init (app ) {     //路由初始化,在Vue實例的beforeCreate生命周期時執行 app:使用了該Vue-router的Vue實例,頁面初始化時執行到這里
    var this$1 = this;                                    //this$1指向VueRouter實例

  "development" !== 'production' && assert(
    install.installed,
    "not installed. Make sure to call `Vue.use(VueRouter)` " +
    "before creating root instance."
  );

  this.apps.push(app);

  // main app already initialized.
  if (this.app) {
    return
  }

  this.app = app;                                         //設置this.app等於app,也就是Vue實例

  var history = this.history;                             //獲取history實例

  if (history instanceof HTML5History) {                  //執行History.transitionTo()進行路由初始化,路由初始化完成后會觸發onReady()注冊的回調函數的。
    history.transitionTo(history.getCurrentLocation());
  } else if (history instanceof HashHistory) {            
    var setupHashListener = function () {
      history.setupListeners();
    };
    history.transitionTo(
      history.getCurrentLocation(),
      setupHashListener,
      setupHashListener
    );
  }

  history.listen(function (route) {
    this$1.apps.forEach(function (app) {
      app._route = route;
    });
  });
};

路由初始胡完成后就會等到<Vue-Link>觸發相應的事件(默認為click)進行路由跳轉了,或者通過push()、go()等函數式編程觸發了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM