Vue中vue-router路由使用示例詳解
前言
Vue Router是Vue框架中非常重要的一個功能。
目標(biāo)
1 單頁面應(yīng)用與多頁面應(yīng)用的區(qū)別;
2 vue-router的具體實現(xiàn)方法;
3 路由模式有哪幾種,有什么區(qū)別;
4 如何進行路由守衛(wèi)與路由緩存;
一 路由的概念
概念
Vue Router是Vue提供的路由管理器。將組件與路由一一對應(yīng)起來,這種對應(yīng)關(guān)系
就路由。
Vue是一個典型的SPA單頁面應(yīng)用框架。SPA單頁面是指網(wǎng)站只有一個html頁面,所有的頁面切換
都只在這個一個頁面中完成。不同組件
的切換全部交由路由
來完成.
單頁面應(yīng)用與多頁面應(yīng)用
在編程開發(fā)興起時,多個html實現(xiàn)頁面的切換,這就是早期的MPA多頁面應(yīng)用
。隨著技術(shù)的發(fā)展,這種頁面切換方式的弊端也逐漸的顯現(xiàn)出來,例如每次切換頁面都需要加載資源用戶體驗極其不好,造成服務(wù)器壓力也非常的大。為了解決多頁面應(yīng)用問題,SPA單頁面應(yīng)用應(yīng)運而生。SPA單頁面應(yīng)用
是指只有一個html頁面,不同組件切換通過路由來實現(xiàn)
。頁面在首次進入時加載相關(guān)的資源,內(nèi)容功能都被封裝到組件中,頁面切換底層變成了組件切換,這樣就解決了多頁面應(yīng)用的很多弊端。但是單頁面應(yīng)用也不是完美無瑕的,首次進入加載相關(guān)資源會導(dǎo)致SPA的首頁加載慢
分類 | 實現(xiàn)方式 | 頁面性能 | 開發(fā)效率 | 用戶體驗 | 首屏加載 | 其他頁面加載 | SEO |
---|---|---|---|---|---|---|---|
單頁 | 一個html | 按需更新性能高 | 高 | 非常好 | 慢 | 快 | 差 |
多頁 | 多個html | 整頁更新性能低 | 一般 | 一般 | 快 | 慢 | 優(yōu) |
SPA單頁面與MPA多頁面應(yīng)用方式各有優(yōu)缺點,根據(jù)自己的項目需要選擇更適合自己項目的開發(fā)方式(現(xiàn)在主流的是SPA應(yīng)用
)。
vue-router
是Vue.js官方的路由插件,它和vue.js是深度集成的,適合用于構(gòu)建單頁面應(yīng)用。
二 準(zhǔn)備工作
1 安裝
npm install vue-router@3.6.5 --save
這個地方需要注意的是你的Vue版本要與vue-router版本對應(yīng)上,否則安裝上也無法使用
vue2.x對應(yīng)的vue-router版本是 vue-router3.x
vue3.x對應(yīng)的vue-router版本是 vue-router4.x
2 引入-注冊-創(chuàng)建路由
import Router from ‘vue-router' // 引入 Vue.use(Router) // 注冊 new Router({})// 創(chuàng)建路由
對于一個項目來說,路由與組件映射不可能只有一兩個。
當(dāng)路由非常多時,將路由配置直接寫在main.js中顯然不太好維護,這里我直接建一個文件來進行路由封裝router.js
import Vue from 'vue' import Router from 'vue-router' // 引入組件 import helloWord from '../views/HelloWord' import School from '../views/School' Vue.use(Router) // 路由與組件綁定 export default new Router({ routes: [ { name:'school', path: '/school', component: School },{ name:'hellword', path: '/helloWord', component: helloWord, }] })
3 全局引入路由
在main.js中全局引入
import router from './router' new Vue({ el: '#app', router, // 引入路由 render: h => h(App), beforeCreate(){ // 全局事件總線 Vue.prototype.$bus = this } }).$mount('#app')
以上全部的準(zhǔn)備工作已完成
若以上操作都沒有問題,可以在控制臺打印vur-router提供的方法$ router、$ route。打印成功就可以使用路由了
$route 每個組件自己的路由信息
$router 全局都一樣,是路由的共用方法
三 路由基本方法
3.1 聲明式導(dǎo)航與編程式導(dǎo)航
聲明式路由導(dǎo)航
聲明式導(dǎo)航是通過在模板中使用特定的指令來實現(xiàn)頁面導(dǎo)航。在Vue模板中,使用< router-link>組件來創(chuàng)建導(dǎo)航鏈接,通過設(shè)置to屬性指定目標(biāo)路由的路徑或命名路由。例如:
<router-link to="/search">跳轉(zhuǎn)到搜索頁面</router-link>
優(yōu)點:簡單直觀,通過在模板中編寫導(dǎo)航鏈接,不需要編寫額外的Js代碼。
編程式導(dǎo)航
編程式導(dǎo)航是通過在Js代碼中使用Vue Router提供的API來實現(xiàn)頁面導(dǎo)航。通過訪問$router對象,可以使用其提供的方法進行頁面跳轉(zhuǎn),例如push、replace、go等。例如:
this.$router.push('/search');
優(yōu)點:可以在Js代碼中根據(jù)條件或動態(tài)數(shù)據(jù)進行導(dǎo)航,更加靈活和可控。
1 聲明式導(dǎo)航
router-link
配置 to 屬性指定路徑(必須) 。本質(zhì)還是a 標(biāo)簽
,to 無需 #
to后面可以是path或name
// to path,默認(rèn)類似 $router.push 跳轉(zhuǎn)路由并增加一條路由歷史記錄 <router-link class="link" to="/helloWord">Helloword</router-link> // to name <router-link class="link" to="helloword">Helloword</router-link> // 替換當(dāng)前歷史記錄,跳轉(zhuǎn)到指定路由 <router-link class="link" replace to="helloword">Helloword</router-link>
2 編程式導(dǎo)航
$router.push
跳轉(zhuǎn)到指定路由,并在路由信息中增加一條歷史信息
<button class="link" @click="jump(1)">hellword</button> jump(type) { console.log('type', type) if (type == 1) { // path 方法跳轉(zhuǎn) // this.$router.push('/helloWord') // this.$router.push({path:'/helloWord'}) // name 方法跳轉(zhuǎn) this.$router.push({name:'hellword'}) } else { this.$router.push('/school') } }
$router.replace
替換當(dāng)前歷史記錄,跳轉(zhuǎn)到指定路由
<button class="link" @click="jump(1)">hellword</button> jump(type) { console.log('type', type) if (type == 1) { this.$router.replace({name:'hellword'}) } else { this.$router.push('/school') } }
$router.go()
可以在瀏覽歷史中前進和后退(正數(shù)- 前進,0 - 刷新,負數(shù) - 后退)
this.$router.go(0) // 刷新 this.$router.go(-1) // 后退1
$ router.back()
在歷史記錄中,后退到上一個頁面
$ router.forward()
在歷史記錄中,前進到下一個頁面
完整代碼
<template> <div id="app"> <hr /> <div class="flex"> <div class="nav"> <h1>方式一</h1> <router-link class="link" to="/helloWord">Helloword</router-link> <router-link class="link" to="/school">school</router-link> <h1>方式二</h1> <button class="link" @click="jump(1)">hellword</button> <button class="link" @click="jump(2)">school</button> </div> <div class="content"> <router-view></router-view> </div> </div> </div> </template> <script> export default { name: "App", data() { return { }; }, mounted() { }, methods: { jump(type) { console.log('type', type) if (type == 1) { // path 方法跳轉(zhuǎn) // this.$router.push('/helloWord') // this.$router.push({path:'/helloWord'}) // name 方法跳轉(zhuǎn) // this.$router.push({name:'hellword'}) } else { this.$router.push('/school') } }, }, }; </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } .flex { display: flex; } .nav { width: 120px; display: flex; flex-direction: column; } .link { margin: 3px 10px; width: 100px; height: 60px; line-height: 60px; font-size: 20px; text-decoration: none; border: 1px solid blue; border-radius: 4px; } .content { width: calc(100% - 100px); height: 800px; background-color: #eee; } </style>
運行效果
3.2 嵌套(多級)路由
school組件下還有student路由,就可以如下方式寫
- children子路由中的path不加/
- 子頁面訪問路徑 /school/student
export default new Router({ routes: [ { name:'school', path: '/school', component: School, children:[{ name:'student', path: 'student', component: Student, }] },{ name:'helloword', path: '/helloWord', component: helloWord, }] })
school組件
<template> <div> <h1>我是School</h1> <hr> <div @click="$router.push('/school/student')">查看學(xué)生</div> <router-view></router-view> </div> </template>
3.3 路由中的參數(shù)
3.3.1 query參數(shù)
顯式傳參
1 路徑后拼接參數(shù)
2 編程式路由中傳query參數(shù)
this.$router.push({path:'/helloWord',query:{id:'01',name:'張二'}})
3 注冊路由傳參
注冊路由時加參數(shù),這個基本不用,了解即可
{ name:'helloword', path: '/helloWord', component: helloWord, query:{ id:'02', name:'張三' } }
3.3.2 params參數(shù)
1 路徑后傳參
path: '/helloWord/:id/:name' // id、name位置對照
2 編程式路由傳參
this.$router.push({name:'helloword',params:{id:'01',name:'張二'}})
特別注意:路由攜帶params參教時,params不能和path一起使用會無效,params只能和name一起使用
params方法只有以上兩種方式傳遞參數(shù)
3.4 命名路由
然后我們可以使用 name 而不是 path 來傳遞 to 屬性給 < router-link>
export default new Router({ routes: [ { name:'school', path: '/school', component: School, children:[{ name:'student', path: 'student', component: Student, }] }] })
3.5 props
路由的props傳參
1 值為對象,該對象中的所有key-value都會以props的形式傳給組件
{ name:'helloword', path: '/helloWord', component: helloWord, props:{id:'003',name:'林淼淼'}, }
<template> <div> <h1>我是HelloWord</h1> </div> </template> <script> export default { name: 'HelloWord', props:['id','name'], // 接收傳參 mounted(){ console.log('=====id======',this.id) console.log('=====name======',this.name) } } </script>
2 布爾值,若值為真,就會把該路由組件收到的所有params參數(shù),以props的形式傳給組件
{ name:'helloword', path: '/helloWord', component: helloWord, props:true }
this.$router.push({name:'helloword',params:{id:'01',name:'張二'}}) <template> <div> <h1>我是HelloWord</h1> </div> </template> <script> export default { name: 'HelloWord', props:['id','name'], // 接收傳參 mounted(){ console.log('=====id======',this.id) console.log('=====name======',this.name) } } </script>
3 值為函數(shù)
{ name:'helloword', path: '/helloWord', component: helloWord, props($route){ // $route組件的路由信息 return {id:$route.query.id,name:$route.query.name} }, query:{ id:'02', name:'張三' } }
<template> <div> <h1>我是HelloWord</h1> </div> </template> <script> export default { name: 'HelloWord', props:['id','name'], // 接收傳參 mounted(){ console.log('=====id======',this.id) console.log('=====name======',this.name) } } </script>
四 路由守衛(wèi)
執(zhí)行順序
4.1 全局路由守衛(wèi)(前/后置)
routes路由中的屬性不可以隨意的自定義,而是要在meta屬性中自定義,其他地方自定義屬性都會失效
Vue.use(Router) const routes = new Router({ routes: [ { name:'school', path: '/school', component: School, meta:{ isAuth:true, title:'學(xué)校' }, children:[{ name:'student', path: 'student', component: Student, meta:{ isAuth:true, title:'學(xué)生' }, }] }, { name:'helloword', path: '/helloWord', component: helloWord, meta:{ isAuth:true, title:'首頁' }, }] })``` **前置路由守衛(wèi) beforeEach**,顧名思義在路由跳轉(zhuǎn)之前執(zhí)行,這里一般可以做頁面權(quán)限校驗等操作 ```c // 前置路由守衛(wèi) /** to 目的地 from 起始地 next 放行 **/ routes.beforeEach((to,from,next)=>{ if(to.meta.isAuth){ next() } })
前置路由守衛(wèi) beforeEach,顧名思義在路由跳轉(zhuǎn)之前執(zhí)行,這里一般可以做頁面權(quán)限校驗等操作。
初始化時候、每次路由切換之前被調(diào)用
// 前置路由守衛(wèi) /** to 目的地 from 起始地 next 放行:路由跳轉(zhuǎn),next下的代碼還會繼續(xù)的執(zhí)行 **/ routes.beforeEach((to,from,next)=>{ if(to.meta.isAuth){ next() }else{ alert('你沒有權(quán)限') } })
后置路由守衛(wèi) afterEach,顧名思義在路由跳轉(zhuǎn)之后執(zhí)行,這里可以做title更改。
初始化時候、每次路由切換之后被調(diào)用
// 后置路由守衛(wèi) /** to 目的地 from 起始地 **/ routes.afterEach((to,form)=>{ document.title = to.meta.title })
4.2 獨享路由守衛(wèi)
獨享路由守衛(wèi) beforEnter,顧名思義就是某一個路由獨自享有的,只由觸發(fā)改路由時才會執(zhí)行類似路由的前置
執(zhí)行順序:全局前置 --> 獨享路由 --> 全局后置
children:[{ name:'student', path: 'student', component: Student, meta:{ isAuth:true, title:'學(xué)生' }, // to form 用法同上 beforeEnter:(to,form,next)=>{ console.log(to,form); next() } }]
4.3 組件內(nèi)路由守衛(wèi)
在組件內(nèi)部設(shè)置該組件的路由守衛(wèi)
beforeRouteEnter 進入該組件時觸發(fā)
beforeRouteLeave 離開該組件時觸發(fā)(切換路由)
<template> <div> <h1>我是HelloWord</h1> </div> </template> <script> export default { name: 'HelloWord', props:['id','name'], data(){ return{} }, // 進入該該組件時觸發(fā) beforeRouteEnter(to,from,next){ console.log('=====enter-to======',to) console.log('=====enter-from======',from) next() }, // 離開該組件時觸發(fā) beforeRouteLeave(to,from,next){ console.log('=====leave-to======',to) console.log('=====leave-from======',from) next() } } </script>
五 其它
5.1 路由模式
1. hash模式
修改為hash模式
const routes = new Router({ // 模式 默認(rèn)為hash mode: 'hash', })
#及其后面的值都是hash值
將打包后的文件發(fā)布到服務(wù)器上(如何沒有線上服務(wù)器可以啟動本地服務(wù)發(fā)布參考:)
hash值有特殊的#標(biāo)識,不會傳送給服務(wù)器端
2. history模式
修改為history模式
const routes = new Router({ // 模式 mode: 'history', })
打包后發(fā)到本地?zé)o服務(wù)上,點擊可以正常的訪問,但是一旦刷新頁面就如下所示,這是因為刷新的時候頁面會當(dāng)成資源去請求服務(wù)器,服務(wù)器找不到此接口就會報錯
解決辦法:
- node中connect-history-api-fallback插件是專門解決此問題的;
- ngix中配置分辨是否前端路由
- 通過后端去處理
3. 總結(jié)
hash模式
1.地址中永遠帶著#號,不美觀。
2.若以后將地址通過第三方手機app分享,若app校驗嚴(yán)格,則地址會被標(biāo)記為不合法。
3.兼容性較好。
4.hash值不會包含在 HTTP 請求中,即: hash值不會帶給服務(wù)器。
history模式
1.地址干凈,美觀。
2.兼容性和hash模式相比略差。
3.應(yīng)用部署上線時需要后端人員支持,解決刷新頁面服務(wù)端404的問題。
5.2 keep-alive緩存路由組件
原理
我們知道vue是通過vnode實現(xiàn)保存節(jié)點的,而keep-alive本身也是通過保存vnode來實現(xiàn)緩存的,而不是直接存儲DOM結(jié)構(gòu)。其實就是將需要緩存的VNode節(jié)點保存在this.cache中,在render時,如果VNode的name符合在緩存條件(可以用include以及exclude控制),則會從this.cache中取出之前緩存的VNode實例進行渲染。
作用
keep-alive組件是vue2.0提供的一個緩存組件,在組件切換過程中把切換出去的組件保留在內(nèi)存,不被銷毀,防止重復(fù)渲染DOM,減少加載時間及性能消耗,提高用戶體驗性
效果
keep-alive組件,只要將子組件嵌套在這里面就可以實現(xiàn)組件的緩存,當(dāng)頁面返回時數(shù)據(jù)不會丟失,實現(xiàn)了我們常見的歷史頁面不刷新的效果
參數(shù)Props
include - 類型字符串、數(shù)組以及正則表達式,只有匹配的組件會被緩存
exclude - 類型字符串、數(shù)組以及正則表達式,匹配的組件不會被緩存
max - 類型字符或者數(shù)字,可以控制緩存組件的個數(shù),緩存組件的最大值
// 只緩存組件name為a或者b的組件 <keep-alive include="a,b"> <component /> </keep-alive> ? // 組件name為c的組件不緩存(可以保留它的狀態(tài)或避免重新渲染) <keep-alive exclude="c"> <component /> </keep-alive> ? // 如果同時使用include,exclude,那么exclude優(yōu)先于include, 下面的例子只緩存a組件 <keep-alive include="a,b" exclude="b"> <component /> </keep-alive> ? // 如果緩存的組件超過了max設(shè)定的值5,那么將刪除第一個緩存的組件 <keep-alive exclude="c" max="5"> <component /> </keep-alive>
用法
1、與include結(jié)合使用
// include 只緩存組件名字為home的組件,其他組件不會緩存,而exclude恰好相反 <keep-alive include="home"> <router-view /> </keep-alive>
2、結(jié)合Router中的meta屬性來控制組件緩存
{ path: '/', name: 'home', meta:{ keepAlive:true // 需要緩存 }, component: Home, children: [ { path: 'goods', name: 'goods', component: Goods, meta: { keepAlive: false // 不需要緩存 } } ] }
<keep-alive> <router-view v-if="$route.meta.keepAlive" /> </keep-alive> <router-view v-if="!$route.meta.keepAlive" />
緩存所有頁面:
在app.vue頁面里加keep-alive
緩存部分頁面:
1、在app.vue頁面里加keep-alive,結(jié)合keep-alive的include屬性
2、結(jié)合Router中的meta屬性,在app.vue頁面里加$route.meta.keepAlive的if判斷
小知識點
1、同時使用include,exclude,那么exclude優(yōu)先于include
2、緩存的組件超過了max設(shè)定的值5,那么將刪除第一個緩存的組件
3、keep-alive 不會在函數(shù)式組件中正常工作,因為它們沒有緩存實例
4、keep-alive 先匹配被包含組件的 name 字段,如果 name 不可用,則匹配當(dāng)前組件 components 配置中的注冊名稱
5、只有組件被 keep-alive 包裹時,這兩個生命周期函數(shù)才會被調(diào)用,如果作為正常組件使用,是不會被調(diào)用的,以及在 2.1.0
版本之后,包含在 keep-alive 中,但符合 exclude ,不會調(diào)用activated和
deactivated這兩個函數(shù)鉤子!另外,在服務(wù)端渲染時,此鉤子函數(shù)也不會被調(diào)用
5.3 生命周期變化
針對路由緩存組件的多加了兩個生命周期函數(shù)
1.activated
- 在 keep-alive 組件激活時調(diào)用
- 該鉤子函數(shù)在服務(wù)器端渲染期間不被調(diào)用
- 使用 keep-alive會將數(shù)據(jù)保留在內(nèi)存中,如果要在每次進入頁面的時候獲取最新的數(shù)據(jù),需要在 activated 階段獲取數(shù)據(jù),承擔(dān)原來 created鉤子函數(shù)中獲取數(shù)據(jù)的任務(wù)。
activated(){ /** * 緩存的組件點擊時調(diào)用 */ },
2.deactivated
- 在 keep-alive 組件停用時調(diào)用
- 該鉤子函數(shù)在服務(wù)器端渲染期間不被調(diào)用
- 被包含在 keep-alive中創(chuàng)建的組件,會多出兩個生命周期的鉤子: activated 與 deactivated
deactivated(){ /** * 緩存的組件點擊時調(diào)用 */ },
總結(jié)
1、如何配置路由?
2、如何使用導(dǎo)航進行路由跳轉(zhuǎn)
聲明式:router-link
編程式:this.$ router.push,this.$ router.g等
3、嵌套(多級)路由如何配置與使用
- 父級路由中加children,children下就是子路由
- 子路由中的path不加/
- 子頁面訪問路徑 /school/student
4、路由如何傳遞傳參
this.$router.push({path:‘/helloWord’,query:{id:‘01’,name:‘張二’}})
this.$router.push({name:‘helloword’,params:{id:‘01’,name:‘張二’}})
props
路徑冒號參數(shù)項:about/:id/:name
5、路由守衛(wèi)
前置守衛(wèi) routes.beforeEach((to,from,next)=>{}) ,后置守衛(wèi) routes.afterEach((to,from,next)=>{})
獨享路由守衛(wèi)
組件內(nèi)路由守衛(wèi)
6、路由緩存
keep-alive
到此這篇關(guān)于Vue中vue-router路由使用示例詳解的文章就介紹到這了,更多相關(guān)vue-router路由使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue中this.$router.go(-1)失效(路由改變了,界面未刷新)
- vue3使用vue-router嵌套多級路由的方法
- vue中路由router配置步驟詳解
- 在vue中路由使用this.$router.go(-1)返回兩次問題
- Vue?router?路由安裝及使用過程
- 解讀Vue-Router?使用?prams?路由傳參失效
- vue使用動態(tài)添加路由(router.addRoutes)加載權(quán)限側(cè)邊欄的方式
- vue3中使用router路由實現(xiàn)跳轉(zhuǎn)傳參的方法
- vue3使用vue-router及路由權(quán)限攔截方式
- Vue3使用vue-router如何實現(xiàn)路由跳轉(zhuǎn)與參數(shù)獲取
相關(guān)文章
element基于el-form智能的FormSmart表單組件
本文主要介紹了element基于el-form智能的FormSmart表單組件,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04Vue二次封裝el-select實現(xiàn)下拉滾動加載效果(el-select無限滾動)
el-select默認(rèn)是不支持虛擬滾動的,需要使用第三方插件來實現(xiàn)虛擬滾動功能,下面這篇文章主要給大家介紹了關(guān)于Vue二次封裝el-select實現(xiàn)下拉滾動加載效果的相關(guān)資料,需要的朋友可以參考下2024-04-04vue2如何使用vue-i18n搭建多語言切換環(huán)境
這篇文章主要介紹了vue2-使用vue-i18n搭建多語言切換環(huán)境的相關(guān)知識,在data(){}中獲取的變量存在更新this.$i18n.locale的值時無法自動切換的問題,需要刷新頁面才能切換語言,感興趣的朋友一起看看吧2023-12-12一文詳解Vue3組件通信輕松玩轉(zhuǎn)復(fù)雜數(shù)據(jù)流
在大型Vue項目中,組件通信如同神經(jīng)網(wǎng)絡(luò)般貫穿整個應(yīng)用,這篇文章將為大家詳細介紹一下Vue3中的組件通信方式,有需要的小伙伴可以了解下2025-02-02Antd的Table組件嵌套Table以及選擇框聯(lián)動操作
這篇文章主要介紹了Antd的Table組件嵌套Table以及選擇框聯(lián)動操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10vuejs數(shù)據(jù)超出單行顯示更多,點擊展開剩余數(shù)據(jù)實例
這篇文章主要介紹了vuejs數(shù)據(jù)超出單行顯示更多,點擊展開剩余數(shù)據(jù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05vue使用Google Recaptcha驗證的實現(xiàn)示例
我們最近的項目中需要使用谷歌機器人驗證,所以就動手實現(xiàn)一下,本文就來詳細的介紹一下vue Google Recaptcha驗證,感興趣的可以了解一下2021-08-08