Vue路由 vue-router知識點詳解
一、什麼是前端渲染,什麼是後端渲染?
1.1 後端渲染
也叫服務端渲染,是指當伺服器擷取到url後,通過一些後端代碼在伺服器中直接将對應的html頁面渲染完畢後,再将頁面傳回給前端進行展示,這就叫做後端渲染。
優點:這種情況下渲染好的頁面,不需要單獨加載任何的js和css,可以交給浏覽器展示,這樣也有利于SEO的優化
缺點:後端人員編寫維護任務太重,前端人員要編寫頁面還需要學習後端代碼,而且這樣做會HTML代碼和資料以及對應的邏輯會混在一起,編寫和維護都非常糟糕。
1.2 後端路由
從上面可以知道,在後端,每一個url就對應了一個頁面,而處理這種url與頁面之間的映射關系的路由關系便是後端路由
當url發生改變時,浏覽器便會向靜态資源伺服器請求html,css,js,然後再通過請求過來的js代碼向API伺服器請求資料
1.3 前後端分離
前後端分離就是把資料操作和顯示分離出來。前端專注做資料顯示,通過文字,圖檔或者圖示等方式讓資料形象直覺的顯示出來。後端專注做資料的操作。前端把資料發給後端,有後端對資料進行修改。
1.4 前端渲染
在浏覽器中顯示的大部分内容,都是由前端寫的js代碼在浏覽器執行,最終渲染出來的頁面。
1.5 SPA頁面
單頁面富應用頁面,最主要的特點就是在前後端分離的基礎上加了一層前端路由
1.6 前端路由
網頁會從一開始就下載下傳所有資源,然後通過一些選項,通過改變url選擇性的加載部分資源,而支援這種功能的技術,便是前端路由,前端路由也是管理url和頁面的映射關系,而前端路由的核心便是改變url,而頁面不會進行整體的重新整理
二、更改URL而不重新整理頁面的方法
2.1 url的hash值
可以在控制台通過 location.hash = ‘aaa’ 修改url的hash值
2.2 HTML5的history模式
可以在控制台通過 history.pushState({} , ’ ’ , ‘aaa’ ) 修改url值,而且這個push其實是在做一個入棧和出棧的操作,在浏覽器可以通過history.back()來回到上一個url,也可以通過前進後退來通路之前的url。
還有一個方法是 history.replaceState( { }, ‘ ‘, ‘aaaa’ ),同樣能修改url而浏覽器不重新整理,但是用這種方法并不會有資料存儲,而是直接替換之前的資料,是以這種方法修改的url不能前進後退
三、vue-router
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-u1p85S4t-1570600486821)(file:///C:\Users\輕狂書生\AppData\Local\Temp\msohtmlclip1\01\clip_image004.jpg)]
3.1 安裝
通過npm安裝,也可以通過腳手架安裝
通過npm安裝時要注意,vue路由應該安裝為運作時依賴,是以後面應該加 --save
3.2 使用
- 在src/router下的index.js檔案中配置,導入vue/vue-router,通過Vue.use(Router)進行插件的安裝,接着new一個router執行個體,接着導出router執行個體,在main.js中進行導入,然後在vue執行個體中進行使用
- 導入要使用的元件,在router執行個體中配置routers屬性,裡面每一個路由都是一個對象,對象中有path:對應的url,component:對應的元件
- 在APP.vue中使用來設定路由選擇項,渲染出來為一個标簽,再通過設定元件顯示出來的位置
具體代碼如下:
Index.js:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../components/Home' //導入要使用的元件
import About from '../components/About'
Vue.use(Router)
export default new Router({
routes: [
{ //每一個路由都是一個對象
path:"/home", //path用于設定url後面跟的東西
component:Home //component表示這個path對應的元件
},
{
path:"/about",
component:About
}
]
})
Main.js
import Vue from 'vue'
import App from './App'
import router from './router' //導入路由
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router, //使用路由
render: h => h(App)
})
App.js
<template>
<div id="app">
<router-link to="/home">首頁</router-link>
<!-- 通過<router-link to="">設定對應的路由 -->
<router-link to="/about">關于</router-link>
<router-view></router-view>
<!-- 通過<router-view>設定元件顯示的位置 -->
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
3.3 預設路徑設定
很簡單,隻需要在routes屬性中再定義一個對象,對象中使用redirect重定向一下路徑
{ //設定預設路徑,當路徑為空是,把路徑重定向到另一個路徑,這裡是重定向到首頁
path:"",
redirect:"/home" //redirect:重定向
}
這樣當路徑為空時,會自動轉到home的路徑
3.4.将浏覽器的url模式設定為history模式
我們使用路由時,預設使用的是hash模式,這樣的壞處是在url中會有一個#号,是以我們可以把模式設定為history,這樣就沒有#号了。
也很簡單,隻需要在router執行個體中設定一個mode屬性為history即可
export default new Router({
routes,
mode:'history' //将路徑模式設定為HTML5的history模式,這樣就不會有#号了
})
記得加引号,沒有就會報錯
3.5.router-link标簽的補充屬性
3.5.1.tag
标簽預設的話會被渲染成a标簽,而tag這個屬性的作用便是将渲染成其他标簽
<template>
<div id="app">
<router-link to="/home" tag="button">首頁</router-link>
<!-- 通過<router-link to="">設定對應的路由,渲染出來為一個a标簽 -->
<router-link to="/about" tag="button">關于</router-link>
<router-view></router-view>
<!-- 通過<router-view>設定元件顯示的位置 -->
</div>
</template>
可以看到,通過tag=”button”這個屬性,屬性被渲染成了一個button按鈕。
3.5.2.replace
當我們用mode=’history’屬性将浏覽器的url模式從hash變成history之後,每次更改url時,浏覽器都是用pushState()方法來更改,這樣的好處是有曆史記錄,使用者可以通過前進後退來通路曆史頁面。但有些時候我們不想使用者可以通路曆史頁面,這個時候就可以使用replace屬性,用法很簡單,直接在标簽中添加一個replace屬性就好了。
這樣使用者在通路時就不能前進後退了
3.5.3.router-link-active
當我們的标簽處于活躍狀态時,浏覽器會自動給它加上一個這個樣式
是以當需要在添加樣式的時候,可以直接給router-link-active添加樣式
如果我們想修改這個樣式的名字,可以在router執行個體中有一個linkrouteractive屬性,
可以通過這個屬性修改名字
linkrouteractive:”active”
3.6.通過代碼修改路由
在上面我們說了設定路由之後可以通過的方式來修改路由
第二種修改路由的方法便是通過代碼修改路由,在原來router-link的地方可以通過兩個button來代替
router-link,然後給這兩個按鈕綁定一個點選事件,在事件中通過this.$router.push()來修改路由
<button @click="homeclick">首頁</button>
<button @click="aboutclick">首頁</button>
methods: {
homeclick(){
this.$router.push('/home') //通過代碼的方式來修改router
},
aboutclick(){
this.$router.push('/about')
},
},
3.7.動态路由
我們之前寫的路由都是靜态的已經寫死的,而我們現在需要動态的來決定路由
同樣的,我們需要先定義一個元件,然後将它導入,然後在routes裡定義路由
{
path:"/User/:userid",
component:User
}
隻不過這次我們在後面加上了 :userid ,這個變量便是我們要動态擷取的值
接着我們在App.vue中使用router-link使用這個路由
可以看到,我們用v-bind指令綁定了to屬性,然後在user後面加上了一個變量userid,
這個變量在下面的data中定義
export default {
name: 'App',
data() {
return {
userid:"zhangsan"
}
},
通過這種方式我們就能動态的擷取到userid的值,進而實作動态的路由。
而要是想擷取到url中的userid的值,我們需要通過$route.params.userid
<h2>{{ $route.params.userid }}</h2>
<!-- $route代表正在活躍的路由,而之前使用的$router代表我們new出來的路由執行個體 -->
要注意差別 r o u t e 和 route和 route和router
3.8.路由的懶加載
懶加載就是指用到時再加載
路由懶加載的寫法:
const Home = () => import('../components/Home')
const About = () => import('../components/About')
const User = () => import('../components/User') //路由的懶加載方式寫法
可以看到,先定義一個常量,然後後面用箭頭函數的形式指派給它一個import,import裡跟上元件的路徑,這樣懶加載便寫好了
3.9.嵌套路由的使用
首先,依舊是導入元件(記得使用懶加載的寫法)
const HomeNews = () => import('../components/HomeNews')
const HomeMessage = () => import('../components/HomeMessage')
接着便是使用,而嵌套路由的使用是在需要嵌套的路由中,加入一個children屬性,傳入一個數組,在這個屬性中使用我們的子路由,在我們的嵌套路由裡一樣可以使用預設值
{ //每一個路由都是一個對象
path:"/home", //path用于設定url後面跟的東西
component:Home, //component表示這個path對應的元件
children:[ //嵌套路由在要嵌套的路由裡使用children屬性,傳入一個數組
{
path:'', //在子路由中,依舊可以設定預設值
component:HomeNews
},
{
path:'news', //在子路由裡,前面不用寫斜杠
component:HomeNews
},
{
path:'message',
component:HomeMessage
}
]
},
接着就是在我們嵌套的元件中使用被嵌套的元件了,注意to屬性不要寫錯了
<template>
<div>
<h2>我是首頁</h2>
<p>我是内容,啊哈哈哈</p>
<router-link to="/home/news">新聞</router-link>
<router-link to="/home/message">資訊</router-link>
<router-view></router-view>
</div>
</template>
這樣嵌套路由就寫好了
3.10.路由傳遞參數的方式
- 通過params方式
首先在index.js中的routers中設定路由,在路徑後面用冒号接收一個變量
{
path:"/User/:userid",
component:User
}
在APP.vue中的router-link中 通過v-bind綁定to屬性,在後面加上變量用于傳遞
最後在User元件中通過$route.params.userid擷取參數值
<template>
<div>
<h2>我是使用者</h2>
<p>我是内容,嘿嘿嘿</p>
<h2>{{ $route.params.userid }}</h2>
<!-- $route代表正在活躍的路由,而之前使用的$router代表我們new出來的路由執行個體 -->
</div>
</template>
- 通過query傳遞
所謂query,就是url後面用?進行連接配接的資料
http://localhost:8081/profile?name=YoRHa&age=18&height=1.88
使用query時index.js中的routers配置正常寫
{
path:"/profile",
component:Profile
}
但是App.vue中的router-link中依舊需要用v-bind綁定to,然後to的值改為一個對象,第一個path依舊為所前往的路徑,第二個參數query也是一個對象便是我們要傳的值
最後在Profile中我們便可以通過$route.query.name來使用傳遞的值了
3.11. r o u t e r 和 router和 router和route是有差別的
r o u t e r : 為 V u e R o u t e r 實 例 , 想 要 導 航 到 不 同 u r l , 則 使 用 router:為VueRouter執行個體,想要導航到不同url,則使用 router:為VueRouter執行個體,想要導航到不同url,則使用router.push()方法
$route:為目前router跳轉對象,裡面可以擷取name,path,query,params等
3.12.導航守衛
vue-router提供的導航守衛主要是用來監聽路由的進入和離開的
①前置守衛 router.beforeEach((to,from,next)=>{next()}) //在跳轉前回調
其中,to是指進入到哪個路由去,form指從哪個路由跳轉過來,而next()是必須執行的函數,表示是否要展示你要看到的路由頁面,調用該方法後,才能進入下一個鈎子
是以當我們想在路由跳轉的同時修改title時,我們可以這麼做:
首先在每個router中定義title值
{
path:"/about",
component:About,
meta:{
title:"關于",
},
},
然後我們來設定導航守衛,這裡是指當跳轉發生時,将to頁面的titlt值賦給document的title,next()是必須執行的,表示要展示我們要看到的頁面
router.beforeEach((to,from,next)=>{
document.title = to.matched[0].meta.title
next()
})
Ps:注意,這裡的router是我們自己定義的Router執行個體,通過腳手架安裝預設好像是沒有的
const router = new Router({
routes,
mode:'history' //将路徑模式設定為HTML5的history模式,這樣就不會有#号了
})
②後置鈎子
router.afterEach((to,from)=>{}) //在跳轉後回調,沒有next()
以上的前置守衛和後置鈎子,都是全局守衛
2.路由獨享的守衛
beforeEnter((to,from,next)=>{}) 直接在路由中使用,參數使用和全局的一樣
使用之後在進入之前進行調用
{
path:"/about",
component:About,
meta:{
title:“關于”,
},
beforeEnter: (to, from, next) => {
console.log(‘about beforeEnter’)
next()
}
},
3.元件内的守衛
①beforeRouteEnter((to,from,next)=>{})
②beforeRouteUpdata((to,from,next)=>{})
③befroeRouteLeave((to,from,next)=>{})
3.13.keep-alive
1.Keep-alive标簽的作用是對元件進行一個緩存,使元件保持活着的狀态,不會被銷毀,正常的元件在路由跳轉之後都會調用distroyed()生命周期鈎子,在跳轉回來之後再調用created()生命周期鈎子。而使用keep-alive将Router-view包裹後,其中的元件在路由跳轉後不會被銷毀,會被緩存起來。
2.在使用keep-alive之後,可以使用兩個函數,activated/deactivated,因為元件不會被銷毀,是以相應的元件的狀态變為了活躍和非活躍狀态,當元件變為活躍時,會調用activated,變為不活躍時,會調用deactivated。這兩個隻有在使用了keep-alive時才有生效。
3.Keep-alive還有兩個重要的屬性:1.include 2.exclude
Include表示隻有比對的元件會被緩存
Exclude表示隻有比對的元件不會被緩存
這裡的比對可以是正則或者是元件中定義的name屬性
4.關于在跳轉後保持原來元件的點選路徑:可以在befroeRouteLeave元件内守衛記錄離開前的路徑,然後通過activated修改路徑
activated() {
this.$router.push(this.path) //當元件變為活躍狀态時回調的函數,這裡轉變為離開前的路徑
},
beforeRouteLeave (to, from, next) {
this.path = this.$route.path //元件内的守衛,記錄了離開時的路徑
next()
}
Keep-alive标簽的作用是對元件進行一個緩存,使元件保持活着的狀态,不會被銷毀,正常的元件在路由跳轉之後都會調用distroyed()生命周期鈎子,在跳轉回來之後再調用created()生命周期鈎子。而使用keep-alive将Router-view包裹後,其中的元件在路由跳轉後不會被銷毀,會被緩存起來。
2.在使用keep-alive之後,可以使用兩個函數,activated/deactivated,因為元件不會被銷毀,是以相應的元件的狀态變為了活躍和非活躍狀态,當元件變為活躍時,會調用activated,變為不活躍時,會調用deactivated。這兩個隻有在使用了keep-alive時才有生效。
3.Keep-alive還有兩個重要的屬性:1.include 2.exclude
Include表示隻有比對的元件會被緩存
Exclude表示隻有比對的元件不會被緩存
這裡的比對可以是正則或者是元件中定義的name屬性
4.關于在跳轉後保持原來元件的點選路徑:可以在befroeRouteLeave元件内守衛記錄離開前的路徑,然後通過activated修改路徑
activated() {
this.$router.push(this.path) //當元件變為活躍狀态時回調的函數,這裡轉變為離開前的路徑
},
beforeRouteLeave (to, from, next) {
this.path = this.$route.path //元件内的守衛,記錄了離開時的路徑
next()
}