vue-router簡(jiǎn)單講解

api文檔

一. 安裝和引入

直接下載 / CDN

https://unpkg.com/vue-router/dist/vue-router.js

Unpkg.com 提供了基于 NPM 的 CDN 鏈接。上面的鏈接會(huì)一直指向在 NPM 發(fā)布的最新版本。你也可以像https://unpkg.com/vue-router@2.0.0/dist/vue-router.js 這樣指定 版本號(hào) 或者 Tag。

在 Vue 后面加載 vue-router,它會(huì)自動(dòng)安裝的:

// html
<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>
NPM
npm install vue-router --save

如果在一個(gè)模塊化工程中使用它,必須要通過(guò) Vue.use() 明確地安裝路由功能:

// main.js

import Vue from 'vue'
import router from 'vue-router'

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
});

如果使用全局的 script 標(biāo)簽,則無(wú)須如此(手動(dòng)安裝)。

構(gòu)建開(kāi)發(fā)版

如果你想使用最新的開(kāi)發(fā)版,就得從 GitHub 上直接 clone,然后自己 build 一個(gè) vue-router。

git clone https://github.com/vuejs/vue-router.git node_modules/vue-router
cd node_modules/vue-router
npm install
npm run build
引入
router.js 的配置

在src文件夾下創(chuàng)建router文件并新建一個(gè)router.js文件
首先引入 vue-router組件,Vue.use是用來(lái)加載全局組件的。那下面我們就開(kāi)始看看這個(gè)VueRouter的寫法和配置吧。

mode:

默認(rèn)為hash,但是用hash模式的話,頁(yè)面地址會(huì)變成被加個(gè)#號(hào)比較難看了http://localhost:8080/#/linkParams/xuxiao
所以一般我們會(huì)采用 history模式,它會(huì)使得我們的地址像平常一樣。http://localhost:8080/linkParams/xuxiao

base
應(yīng)用的基路徑。例如,如果整個(gè)單頁(yè)應(yīng)用服務(wù)在 /app/ 下,然后 base 就應(yīng)該設(shè)為 "/app/"。
一般寫成 __dirname,在webpack中有配置。

routes
routes:就是我們的大核心了,里面包含我們所有的頁(yè)面配置。
path:很簡(jiǎn)單,就是我們的訪問(wèn)這個(gè)頁(yè)面的路徑
name:給這個(gè)頁(yè)面路徑定義一個(gè)名字,當(dāng)在頁(yè)面進(jìn)行跳轉(zhuǎn)的時(shí)候也可以用名字跳轉(zhuǎn),要唯一喲
component:組件,就是咱們?cè)谧钌厦嬉氲?import ...了,當(dāng)然這個(gè)組件的寫法還有一種懶加載

懶加載的方式,我們就不需要再用import去引入組件了,直接如下即可。懶加載的好處是當(dāng)你訪問(wèn)到這個(gè)頁(yè)面的時(shí)候才會(huì)去加載相關(guān)資源,這樣的話能提高頁(yè)面的訪問(wèn)速度。
component: resolve => require(['./page/linkParamsQuestion.vue'], resolve)

//  router下的index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router);

export default new Router({
  mode:"history",
  routes: [
    {
      path: '/more/fag',
      name: 'fag',
      component: fag
    },
    {
      path: '/',
      name: 'followers',
      component: follower
    },
    {
      path: '/followers',
      name: 'followers',
      component: follower
    },
    {
      path: '/likes',
      name: 'like',
      component: like
    },
    {
      path: '/more',
      name: 'more',
      component: more,
      children:[
        // {
        //   path: '/more/fag',
        //   name: 'fag',
        //   component: fag,
        // }
      ]
    }
  ]
})

二. router的使用

1. router傳參
路由匹配參數(shù)

首先在路由配置文件router.js中做好配置。標(biāo)紅出就是對(duì) /linkParams/的路徑做攔截,這種類型的鏈接后面的內(nèi)容會(huì)被vue-router映射成name參數(shù)。


3863065028-5932ec92b04df_articlex.png

代碼中獲取name的方式:

let name = this.$route.params.name; // 鏈接里的name被封裝進(jìn)了 this.$route.params
Get請(qǐng)求傳參

如同:你完全可以在鏈接后加上?進(jìn)行傳參。
示例:http://localhost:8080/linkParamsQuestion?age=18
項(xiàng)目里獲取:

let age = this.$route.query.age; //問(wèn)號(hào)后面參數(shù)會(huì)被封裝進(jìn) this.$route.query;
編程式導(dǎo)航

這里就開(kāi)始利用vue-router講發(fā)起跳轉(zhuǎn)了。其實(shí)也非常簡(jiǎn)單,主要利用 <router-link>來(lái)創(chuàng)建可跳轉(zhuǎn)鏈接,還可以在方法里利用 this.$router.push('xxx') 來(lái)進(jìn)行跳轉(zhuǎn)。

樣例: <router-link to="/linkParams/xuxiao">點(diǎn)我不會(huì)懷孕</router-link>
上面的這個(gè)router-link就相當(dāng)于加了個(gè)可跳轉(zhuǎn)屬性。

至于this.$router.push這里直接用官網(wǎng)的荔枝了

// 字符串,這里的字符串是路徑path匹配噢,不是router配置里的name
this.$router.push('home')

// 對(duì)象
this.$router.push({ path: 'home' })

// 命名的路由 這里會(huì)變成 /user/123
this.$router.push({ name: 'user', params: { userId: 123 }})

// 帶查詢參數(shù),變成 /register?plan=private
this.$router.push({ path: 'register', query: { plan: 'private' }})
導(dǎo)航鉤子

導(dǎo)航鉤子函數(shù),主要是在導(dǎo)航跳轉(zhuǎn)的時(shí)候做一些操作,比如可以做登錄的攔截,而鉤子函數(shù)根據(jù)其生效的范圍可以分為 全局鉤子函數(shù)、路由獨(dú)享鉤子函數(shù)和組件內(nèi)鉤子函數(shù)。

全局鉤子函數(shù)

可以直接在路由配置文件router.js里編寫代碼邏輯。可以做一些全局性的路由攔截。

router.beforeEach((to, from, next)=>{
  //do something
  next();
});
router.afterEach((to, from, next) => {
    console.log(to.path);
});

每個(gè)鉤子方法接收三個(gè)參數(shù):

to: Route: 即將要進(jìn)入的目標(biāo) 路由對(duì)象

from: Route: 當(dāng)前導(dǎo)航正要離開(kāi)的路由

next: Function: 一定要調(diào)用該方法來(lái) resolve 這個(gè)鉤子。執(zhí)行效果依賴 next 方法的調(diào)用參數(shù)。

next(): 進(jìn)行管道中的下一個(gè)鉤子。如果全部鉤子執(zhí)行完了,則導(dǎo)航的狀態(tài)就是 confirmed (確認(rèn)的)。

next(false): 中斷當(dāng)前的導(dǎo)航。如果瀏覽器的 URL 改變了(可能是用戶手動(dòng)或者瀏覽器后退按鈕),那么 URL 地址會(huì)重置到 from 路由對(duì)應(yīng)的地址。

next('/') 或者 next({ path: '/' }): 跳轉(zhuǎn)到一個(gè)不同的地址。當(dāng)前的導(dǎo)航被中斷,然后進(jìn)行一個(gè)新的導(dǎo)航。

確保要調(diào)用 next 方法,否則鉤子就不會(huì)被 resolved。

路由獨(dú)享鉤子函數(shù)

可以做一些單個(gè)路由的跳轉(zhuǎn)攔截。在配置文件編寫代碼即可

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
組件內(nèi)鉤子函數(shù)

更細(xì)粒度的路由攔截,只針對(duì)一個(gè)進(jìn)入某一個(gè)組件的攔截。

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對(duì)應(yīng)路由被 confirm 前調(diào)用
    // 不!能!獲取組件實(shí)例 `this`
    // 因?yàn)楫?dāng)鉤子執(zhí)行前,組件實(shí)例還沒(méi)被創(chuàng)建
  },
  beforeRouteUpdate (to, from, next) {
    // 在當(dāng)前路由改變,但是該組件被復(fù)用時(shí)調(diào)用
    // 舉例來(lái)說(shuō),對(duì)于一個(gè)帶有動(dòng)態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時(shí)候,
    // 由于會(huì)渲染同樣的 Foo 組件,因此組件實(shí)例會(huì)被復(fù)用。而這個(gè)鉤子就會(huì)在這個(gè)情況下被調(diào)用。
    // 可以訪問(wèn)組件實(shí)例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導(dǎo)航離開(kāi)該組件的對(duì)應(yīng)路由時(shí)調(diào)用
    // 可以訪問(wèn)組件實(shí)例 `this`
  }
}
其他知識(shí)點(diǎn)
滾動(dòng)行為

在利用vue-router去做跳轉(zhuǎn)的時(shí)候,到了新頁(yè)面如果對(duì)頁(yè)面的滾動(dòng)條位置有要求的話,可以利用下面這個(gè)方法。

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 期望滾動(dòng)到哪個(gè)的位置
  }
})

scrollBehavior 方法接收 to 和 from 路由對(duì)象。
第三個(gè)參數(shù) savedPosition 當(dāng)且僅當(dāng) popstate 導(dǎo)航 (mode為 history 通過(guò)瀏覽器的 前進(jìn)/后退 按鈕觸發(fā)) 時(shí)才可用。
這里就不細(xì)致的講了,文檔都有也非常簡(jiǎn)單,記住有這個(gè)東西就行。

//所有路由新頁(yè)面滾動(dòng)到頂部:
scrollBehavior (to, from, savedPosition) {
  return { x: 0, y: 0 }
}

//如果有錨點(diǎn)
scrollBehavior (to, from, savedPosition) {
  if (to.hash) {
    return {
      selector: to.hash
    }
  }
}
路由元信息

這個(gè)概念非常簡(jiǎn)單,就是在路由配置里有個(gè)屬性叫 meta,它的數(shù)據(jù)結(jié)構(gòu)是一個(gè)對(duì)象。你可以放一些key-value進(jìn)去,方便在鉤子函數(shù)執(zhí)行的時(shí)候用。
舉個(gè)例子,你要配置哪幾個(gè)頁(yè)面需要登錄的時(shí)候,你可以在meta中加入一個(gè) requiresAuth標(biāo)志位。

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      meta: { requiresAuth: true }
    }
  ]
})

然后在 全局鉤子函數(shù) beforeEach中去校驗(yàn)?zāi)繕?biāo)頁(yè)面是否需要登錄。

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    //校驗(yàn)這個(gè)目標(biāo)頁(yè)面是否需要登錄
    if (!auth.loggedIn()) {  
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 確保一定要調(diào)用 next()
  }
})
這個(gè)auth.loggedIn 方法是外部引入的,你可以先寫好一個(gè)校驗(yàn)是否登錄的方法,再import進(jìn) router.js中去判斷。

項(xiàng)目中出現(xiàn)的問(wèn)題

1. 切換路由后改變組件數(shù)據(jù)
//組件
<template>
    <div>{{header_msg}}</div>

</template>
export default {
         data(){
             return {
                  header_msg:'Get Followers',
             }
         },
          watch: {
            //不同path下  header_msg顯示的信息不同
              '$route' (to, from) {
                  if(to.name === 'like'){
                      this.header_msg = 'Get Likes';
                      this.faq = false
                  }else if(to.name === 'more'){
                      this.header_msg = 'More';
                      this.faq = false
                  }else if(to.name === 'followers'){
                      this.header_msg = 'Get Followers';
                      this.faq = false
                  }else if(to.name === 'fag'){
                      this.faq = true
                  }
              }
          }
    }
2.解決vue-router嵌套路由(子路由)在history模式下刷新無(wú)法渲染頁(yè)面的問(wèn)題
異常描述:

本來(lái)使用的是vue-router的hash模式,但是hash模式下url需要帶“#”符號(hào),不僅看起來(lái)不舒服,而且有些場(chǎng)景下是會(huì)破壞路由中的"#"(微信分享頁(yè)面就會(huì)把"#"后邊的內(nèi)容處理掉),所以就需要使用history模式,然后就讓后端改下nginx配置:

 location / { try_files $uri $uri/ /index.html; } 

vue-router使用history模式+使用嵌套路由:

const router = new Router({
    mode: 'history',
    routes: [
        {
            path: '/',
            component: mall,
            name: 'mall'
        },
        ……

        //我的銀行卡
        {
          path: '/myCard',
          meta: { requireAuth: true },
          component: myCard,
          name: 'myCard',
          children:[
            { path:'', component: card},
            { path:'add', component: add}
          ]
        }
         ……
    ]
})

訪問(wèn)路由和嵌套路由頁(yè)面,顯示正常,但是刷新頁(yè)面的時(shí)候,嵌套路由頁(yè)面css樣式失效了:

解決問(wèn)題:

先考慮的主Vue中以Import的方式引入靜態(tài)樣式文件,的確可行,但是最后發(fā)現(xiàn),直接修改index.html文件中的靜態(tài)文件引入路徑就OK了:

修改前:

<link rel="stylesheet" href="./static/css/layout.css">

修改后

<link rel="stylesheet" href="/static/css/layout.css">
原理:

./ 是指用戶所在的當(dāng)前目錄(相對(duì)路徑);

/ 是指根目錄(絕對(duì)路徑,項(xiàng)目根目錄),也就是項(xiàng)目根目錄;

對(duì)于hash模式,根路徑是固定的,就是項(xiàng)目的根目錄,但是history模式下,以 / 開(kāi)頭的嵌套路徑會(huì)被當(dāng)作根路徑,所以使用“./”引入文件,就會(huì)找不到文件了,因?yàn)槲募旧砭褪窃陧?xiàng)目根目錄下的,并不在嵌套路徑這個(gè)目錄下。

總結(jié),無(wú)論hash模式還是history模式,可以直接使用“/”從項(xiàng)目根目錄引入靜態(tài)文件。

3. Vue默認(rèn)首頁(yè)router激活一直存在
異常描述:

在給router-link-active添加完樣式后在發(fā)現(xiàn)默認(rèn)路由('/')樣式一直存在。
解決:給router-link添加exact屬性

<router-link class="my-bar-item" to="/" exact>首頁(yè)</router-link>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容