vue-router 學(xué)習(xí)整理

概述

vue-router是vue-cli中管理路由的模塊
通過URL,實現(xiàn)URL和組件之間的一一對應(yīng),通過URL進行組件 切換

應(yīng)用場景:
單頁面應(yīng)用 single page application(SPA) 移動端應(yīng)用很廣泛, 沒有真實的頁面跳轉(zhuǎn),只是針對不用URL在頁面內(nèi)容區(qū)域做了不同的渲染
只是加載一次JS、CSS文件,降低了頁面切換時候的 HTTP請求

安裝方式

1.一般在vue-cli初始化(vue init webpack 項目名稱)時候,會有提示 是否安裝vue-router,選擇y回車,即可安裝
2.后續(xù)手動安裝,命令行到指定目錄
輸入:

npm install vue-router --save   //安裝vue-router并添加到依賴
使用

以將代碼放置在入口文件main.js為例

import Vue from 'vue'
import App from './app'
//1.引入模塊
import VueRouter from 'vue-router' 

//2.將vue-router作為Vue的插件
Vue.use(VueRouter)

//3.創(chuàng)建vue-router實例
let router = new VueRouter({
  ...
})

//4.將路由配置信息router掛載到Vue實例
new Vue({
  el: '#app',
  router,  
  template: '<app />'
  components:{
    App    //App為跟組件 App.vue 
  }
})
配置路由

let router = new VueRouter({ ... })
說明:為什么命名router
router是我們的路由實例,命名為變量router是為了方便簡寫,在Vue實例上有個鍵名叫router,兩者相同則可以寫一個鍵名即可

1.簡單配置路由

new VueRouter({
  mode:'history',  //模式分為 hash,history兩種,默認為hash
  linkActiveClass:'xxx', //當前處在激活狀態(tài)下的router-link標簽上的狀態(tài)class名
  scrollBehavior(to,from,saveposition){   //滑動信息 
    ...
  },
  routes:[  //路由調(diào)整信息
    {
      path:'/',  //這個是路徑
      component:xxx,  //這個是對應(yīng)import過來的單文件組件,作為模板
      alias:'/index',  //訪問另一個路徑,扔可以訪問,但是不會觸發(fā)按鈕的激活類名
      name:'indexpage' ,
      meta:{      //定義針對當前路由的自定義數(shù)據(jù)
        needlogin:true
      }
   },{
      path:'/about',
      component:xxx
    },{
      path:'*',    //通配符,標識沒有配置路由的路徑情況,一般作為404
      redirect:{    //重新定向到一個已經(jīng)存在的路由路徑
        path:'xxxx'  
      }
    }
  ]
})

另外,配置路由,引入模板時候,在vue-cli中 @標識src文件夾,可以在webpack.base.conf.js 查看其聲明

2.關(guān)于配置路由中的mode選擇

new VueRouter({
  mode:'hash',    //如果選擇hash模式,鏈接中需要帶#
  routes:[
    ...
  ]
})

建議:
一般低版本瀏覽器使用hash模式
高版本瀏覽器使用history模式

3.關(guān)于配置路由中的重定向redirect

  redirect((to)=>{      //通過箭頭函數(shù),參數(shù)to,可以獲取path路徑,可以更加豐富我們重定向的邏輯
    if(to.path=='xxx'){
      return '/my';  //跳轉(zhuǎn)到我的
    }else{
      return '/';  //跳轉(zhuǎn)到首頁
    }
  })

  //redirect書寫的方式
  redirect:'/about'
  redirect:{path:'/about'}
  redirect:{name:'xxx'} //通過routes中的name,也可以定位 

4.存在二級路徑嵌套時候
默認顯示第一項的需求
在二級嵌套中,如果希望父路由默認顯示第一個子路由信息,且子路由為激活狀態(tài)
則可以將父路由path:'',將子路由的第一項path設(shè)置為父路由原有path

  ...
  {
    path: '/about',
    component: 'xxx',
    children:[
      {
        path:'/about/xxx',    //二級子菜單
        component:'xxxx'
      }
    ]
  }
  ...

使用children嵌套數(shù)據(jù),將子路由對象放進去

5.路由是我們配置瀏覽器跳轉(zhuǎn)的基本配置,在模板頁面中我們需要使用連接來觸發(fā)

<router-link>我是個按鈕</router-link>

router-link屬性:
to="xxx" //相當于a標簽的href,填寫跳轉(zhuǎn)鏈接
tag="li"  //將<router-link>渲染為什么標簽,以便瀏覽器去渲染
event="hover" //如果要添加一個觸發(fā)事件,則用event來聲明,默認click
active-class="xxx"  
//如果標簽對應(yīng)的,路由路徑為當前狀態(tài),則vue-router會默認為其添加激活的狀態(tài)類名
//如果你想自定義自己的激活狀態(tài)class名,則用這個
//另外,自定義狀態(tài)類名有2個位置,一個在路由配置中,一個在這個觸發(fā)按鈕上,
//同時配置,按鈕的優(yōu)先級高,會剔除掉路由上的激活狀態(tài)配置類名

exact 
//如果不采用相對于根路徑 /xxx  那么有可能存在,父路由,子路由同時處于激活class名狀態(tài)下
//此時,添加exact 嚴格模式,以便只有一個路由顯示激活class名      

6.對應(yīng)path有router-link,對應(yīng)的component,應(yīng)該渲染到這里<router-view>

<router-link to="xxxx" tag="li">
  <a>按鈕1</a>    //如果router-link要嵌套a標簽,則a標簽不用再寫href了
</router-link>
<router-link to="xxxx" tag="li">
  <a>按鈕2</a>
</router-link>
//多個按鈕對應(yīng)一個router-view
<router-view></router-view>

7.命名視圖
在路由配置的routes中 path和component是一一對應(yīng)的,
如果我們希望某一個path對應(yīng)多個component時候
如:

//在路由配置文件中
  path:"/about",
  components:{    //注意 components 是復(fù)數(shù)形式
    default: "模板1",  //不寫name的view-router為default
    slider: "模板2"  
  }

//在單文件組件中
//當我們訪問 /about 時候,下面2個router-view會同時顯示
<router-view></router-view>
<router-view name="slider"></router-view>

//在router-view中可以添加class名,
<router-view class="father-box"></router-view>  //router-view中的所有結(jié)構(gòu)都有一個父級class名為father-box

//在單文件組件中
<template>
  <div class="son-box">
      <p>hello</p>
  </div>
</template>

//渲染后
<div class="father-box son-box">  //類名會進行合并
    <p>hello</p>
</div>

8.路由配置中的scrollBehavior
在頁面onload或者瀏覽器前進,后退時候觸發(fā)

scrollBehavior(to,from,saveposition ){
   //to 目標路由
   //from 當前路由
   //saveposition 當前位置
   //可以將當前  saveposition 作為返回值,達到頁面跳轉(zhuǎn),返回后恢復(fù)滾動條位置的效果

   //滾動條滑動頂部位置
   return { x: 0, y: 0 };
}

8.動態(tài)路由
在路由配置中,所有的path都是以一個可預(yù)測的狀態(tài)存在
如果我們希望添加一個格式,不清楚具體數(shù)據(jù),需要使用動態(tài)路由

  //在路由配置中  
  ...
  {
    path:'/students/:userId?',  //其可以匹配 /students,/students/1,/students/2
    component:'xxx'
  }  
  ...
  
  //在單文件組件頁面
  通過 this.$route.params.userId 可以獲取其信息,使得后續(xù)邏輯上更加豐富

9.路由的自定義屬性

  ...
  {
    path:'xxxx',
    component:'xxxx',
    meta:{
      needlogin:true
    }
  }
  ...

  //在單文件組件中,我們可以通過$route中獲取
  this.$route.meta.needlogin
  1. 動態(tài)路由的傳參的新方式,配置props: true
  • 通常方式
//---路由部分
routes:[
  {
    path:'/categories/edit/:id?' 
    component:'xxx'
  }
]
//---單文件組件中
created(){
   console.log(this.$route.params.id);
}
  • 新的傳遞params方式:
    路由中props為true,代表將連接中任何參數(shù),以props方式注入到新組件中去
//---路由部分
routes:[
  {
    path:'/categories/edit/:id?' 
    component:'xxx',
    props: true
  }
]
//---單文件組件中
props:[
  'id'
]
router 與 $route

router是我們創(chuàng)建的VueRouter實例
$route是當前單文件組件的路由實例

router實例方法 實現(xiàn) 【編程式導(dǎo)航】

//直接跳轉(zhuǎn)
router.push('/about')
router.push({ path: '/about' })

//動態(tài)路由,單文件頁面通過 this.$route.params.userId 獲取傳遞信息
router.push({ name: 'about', params: { userId: '123' }})

//查詢字符串方式,用戶訪問有權(quán)限的頁面,直接跳轉(zhuǎn)到登錄頁,
//登錄完成后,通過this.$route.query.redirect 獲取用戶之前想去的頁面,然后通過push,再次跳轉(zhuǎn)
//實現(xiàn) 未登錄狀態(tài)->登錄->登錄后自動跳轉(zhuǎn)用戶之前想去的 權(quán)限限制頁面
router.push({ path: '/login', query: { redirect: '/user' }})

其他方法:

  router.repalce( '/xxx' ) 
//將歷史記錄中的當前步驟替換掉,并且完成跳轉(zhuǎn)

  router.go(number)  
  // 填寫具體數(shù)字,針對history的當前步數(shù),向前是負值,向后是正值,但是只能在歷史步數(shù)內(nèi),超過則不作操作

vue-router生命周期 鉤子

全局鉤子函數(shù)

所有路由進入,出去都會觸發(fā)此鉤子函數(shù)

  1. beforeEach
    還沒有進入路由內(nèi),所有不能獲取vue實例
    如果此時此刻想獲取,可以通過router.app方式,得到vue實例
let router = new VueRouter({...})

router.beforeEach(function(to,from,next){
    console.log(to); //目標導(dǎo)航
    console.log(from);  //離開導(dǎo)航
    next(); //執(zhí)行則路由跳轉(zhuǎn)

    //實際例子,根據(jù)路由情況,判斷是否需要登錄
    //根據(jù)目標路徑下的 自定義屬性meta(如果你設(shè)置了),如 
    ...
    {
        path:'/xxx'
        component:'xxx',
        meta:{              //meta提供開發(fā)者掛載自定義數(shù)據(jù)
            needLogin:true      //xxx頁面需要登錄
        }
    }
    ...

    //如果跳轉(zhuǎn)到xxx頁面,則跳轉(zhuǎn)到登錄/login,否則路由正常跳轉(zhuǎn)
    if(to.meta.needLogin){
        next('/login');
    }else{
        next();
    }

})
  1. afterEach
rourer.afterEach(function(to,from){
    //路由跳轉(zhuǎn)后,我們可以做一些操作
    //例如: 根據(jù)path或者meta添加新屬性,去判斷,改變文檔標題

    if(to.path=='/'){
        window.document.title = 'xxx'
    }else if{
        ...
    }else{
        ...
    }
});

局部鉤子函數(shù)

beforeEnter 針對某一個路由,進行處理

  ...,
  {
    path:'xxx'
    component:'xxx',
    beforeEnter(to,from,next){
        //只是針對xxx這個path,做操作
        next();  //next必須執(zhí)行,否則會卡住
    }   
  },
  ...
單文件組件中的鉤子函數(shù)
優(yōu)先順序從【0】開始

<script>
data(){
    return{
        msg:'hello'
    }
},
created(){
     console.log("創(chuàng)建完成:");
     console.log(this.$el);
},
beforeCreate(){  【2】
    //組件執(zhí)行的第一個鉤子函數(shù)   
},
beforeRouteEnter(to,from,next){【1】
    //訪問導(dǎo)航時候,執(zhí)行這個路由執(zhí)行的第一的函數(shù)   
    //這個時候組件還沒有初始化,無法訪問this

    console.log(this) //undefined

    next(function(vm){  //next中函數(shù)的參數(shù),參數(shù)vm就是vue實例
        //vm就是當前組件實例
        console.log(vm.msg);  //'hello'
    })
},
beforeRouteUpdata(to,from,next){
    //這個是路由嵌套情況下,點擊子導(dǎo)航觸發(fā)
    console.log('beforeRouteUpdata');
      
    next(); //不寫這個鉤子函數(shù)不會繼續(xù)執(zhí)行

        console.log(this) //可以訪問組件實例
},
beforeRouteLeave(to,from,next){
    //離開主導(dǎo)航(主組件)時候觸發(fā)
}

</script>

路由的細節(jié)問題

  1. 同一個路由地址,query參數(shù)不同,點擊通過$router.push從當前路由地址,跳轉(zhuǎn)到當前路由地址,參數(shù)變化
//傳值
this.$router.push({path:"/menLink",query:{alert:"頁面跳轉(zhuǎn)成功"}})
//用query獲取值
<p>提示:{{this.$route.query.alert}}</p>

頁面不重新渲染的情況,只需要對 <router-view></router-view> 增加屬性key

 <router-view :key="$route.fullPath" ></router-view>

1-2. 當兩個不同的path,對應(yīng)相同的component的時候;
在兩個路由之間切換,不會改變router-view視圖更新
如:

{
  path: '/create',
  component:Categories
},{
  path: '/edit/:id',
  component:Categories
}

解決方法:
綁定key屬性

<router-view :key="$route.path"></router-view>

1-3.當兩個相同的path,對應(yīng)相同的component的時候;
在兩個路由之間切換,不會觸發(fā)created的生命周期函數(shù),不會對router-view進行視圖更新
如:

{
  path: '/article/:id',
  component:Article
}

id=1 與 id=2 兩個情況,切換時候碰到
解決方法:
需要針對id進行watch,之后強制觸發(fā)created中的數(shù)據(jù)獲取函數(shù)
如:

watch:{
  id : function(){
    //請求對應(yīng)ID下的數(shù)據(jù),進行視圖渲染
    this.getDataByIdFn();
  }
},
created(){
  //默認進入獲取
  this.getDataByIdFn();
}
  1. ios 和 safari下,相同path但query修改,跳轉(zhuǎn)后,會出現(xiàn)頁面不渲染的情況,因此使用window.location.reload刷新頁面
this.$router
.push({ path: "/college", query: { DeptInfo: id } })
.then(() => {
    window.location.reload();
});

生命周期相關(guān)

組件內(nèi)路由

  • beforeRouteEnter
beforeRouteEnter(to, from, next){
    // 無法獲取this,只能通過vm獲取
    next(vm => {
      vm.routeFrom = from.name
      vm.routeTo = to.name
    })
}
  • beforeRouteLeave
beforeRouteLeave(to, from, next){
    this.routeFrom = from.name
    this.routeTo = to.name
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容