本文旨在介紹 vue-router 的實(shí)現(xiàn)思路,并動(dòng)手實(shí)現(xiàn)一個(gè)簡(jiǎn)化版的 vue-router 。我們先來(lái)看一下一般項(xiàng)目中對(duì) vue-router 最基本的一個(gè)使用,可以看到,這里定義了四個(gè)路由組件,我們只要在根 vue 實(shí)例中注入該 router 對(duì)象就可以使用了.
import VueRouter from 'vue-router';import Home from '@/components/Home';import A from '@/components/A';import B from '@/components/B'import C from '@/components/C'Vue.use(VueRouter)export default new VueRouter.Router({ // mode: 'history', routes: [ {  path: '/',  component: Home }, {  path: '/a',  component: A }, {  path: '/b',  component: B }, {  path: '/c',  component: C } ]})vue-router 提供兩個(gè)全局組件, router-view 和 router-link ,前者是用于路由組件的占位,后者用于點(diǎn)擊時(shí)跳轉(zhuǎn)到指定路由。此外組件內(nèi)部可以通過(guò) this.$router.push , this.$rouer.replace 等api實(shí)現(xiàn)路由跳轉(zhuǎn)。本文將實(shí)現(xiàn)上述兩個(gè)全局組件以及 push 和 replace 兩個(gè)api,調(diào)用的時(shí)候支持 params 傳參,并且支持 hash 和 history 兩種模式,忽略其余api、嵌套路由、異步路由、 abstract 路由以及導(dǎo)航守衛(wèi)等高級(jí)功能的實(shí)現(xiàn),這樣有助于理解 vue-router 的核心原理。本文的最終代碼不建議在生產(chǎn)環(huán)境使用,只做一個(gè)學(xué)習(xí)用途,下面我們就來(lái)一步步實(shí)現(xiàn)它。
install實(shí)現(xiàn)
任何一個(gè) vue 插件都要實(shí)現(xiàn)一個(gè) install 方法,通過(guò) Vue.use 調(diào)用插件的時(shí)候就是在調(diào)用插件的 install 方法,那么路由的 install 要做哪些事情呢?首先我們知道 我們會(huì)用 new 關(guān)鍵字生成一個(gè) router 實(shí)例,就像前面的代碼實(shí)例一樣,然后將其掛載到根 vue 實(shí)例上,那么作為一個(gè)全局路由,我們當(dāng)然需要在各個(gè)組件中都可以拿到這個(gè) router 實(shí)例。另外我們使用了全局組件 router-view 和 router-link ,由于 install 會(huì)接收到 Vue 構(gòu)造函數(shù)作為實(shí)參,方便我們調(diào)用 Vue.component 來(lái)注冊(cè)全局組件。因此,在 install 中主要就做兩件事,給各個(gè)組件都掛載 router 實(shí)例,以及實(shí)現(xiàn) router-view 和 router-link 兩個(gè)全局組件。下面是代碼:
const install = (Vue) => { if (this._Vue) { return; }; Vue.mixin({ beforeCreate() {  if (this.$options && this.$options.router) {  this._routerRoot = this;  this._router = this.$options.router;  Vue.util.defineReactive(this, '_routeHistory', this._router.history)  } else {  this._routerRoot = (this.$parent && this.$parent._routerRoot) || this  }  Object.defineProperty(this, '$router', {  get() {   return this._routerRoot._router;  }  })  Object.defineProperty(this, '$route', {  get() {   return {   current: this._routerRoot._routeHistory.current,   ...this._routerRoot._router.route   };  }  }) } }); Vue.component('router-view', { render(h) { ... } }) Vue.component('router-link', {  props: {  to: String,  tag: String, }, render(h) { ... } }) this._Vue = Vue;}            
新聞熱點(diǎn)
疑難解答
圖片精選