Router
SPA ( single page App ) 單頁面應用
- 多頁面應用
有多個html文件,通過a標籤的連接聯通各個頁面
- 缺點
- 開發起來太冗餘,編譯、壓縮很耗時間
- 頁面之間的跳轉速度太慢,這個時候就會出現一個嚴重的問題,白屏
- 單頁面應用
- 不需要刷新頁面,因爲它就是一個頁面
- 這個頁面內容在切換
- 單頁面內容之間的切換要想實現我們就是用路由了
- 如今我們的app、後臺管理系統 主要的開發形式就是spa
vue路由功能
- 實現單頁面的切換
- 路由攜帶參數
- 路由的導航守衛
- 路由進行數據預載(進入組件前就請求獲得數據)
vue-router 基礎
- vue 路由的mode(模式)有幾種, 分別是什麼?在那些環境下運行?
-
hash: 使用 URL hash 值來作路由。支持所有瀏覽器,包括不支持 HTML5 History Api 的瀏覽器。 /#home
-
history: 依賴 HTML5 History API 和服務器配置。【需要後端支持】 /home
-
abstract: 支持所有 JavaScript 運行環境,如 Node.js 服務器端。如果發現沒有瀏覽器的 API,路由會自動強制進入這個模式。【 這個模式不常用 】
-
- 路由的使用步驟
-
安裝 vue-router
yarn add vue-router
-
在src目錄下創建一個router目錄, 裏面創建一個index.js文件 , 這個目錄就是router的模塊
-
引入第三方的依賴包, 並註冊路由
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use( VueRouter ) //使用vue-router這個第三方插件
注意: import這個關鍵字要放在整個文件的上層
-
創建了一個router對象實例,並且創建路由表
const routes = [ { path: '/home', component: Home }//每一個對象就是一個路由 ] const router = new VueRouter({ routes//路由表 必寫的 })
-
導出router實例
export default router
-
入口文件main.js中引入路由實例 router , 然後在根實例中註冊
import router from './router/index.js' new Vue({ router, render: (h) => App }).$mount('#app')
-
給路由一個路由展示區域
- 如果是以及路由, 那麼我們放在App組件中,用一個 router-view 的組件表示
<router-view />
-
當頁面第一次的打開的時候, 需要做一個重定向, 就是要自動跳轉到 /home 這個路由上
const routes = [ { //我們要求這個路由的配置要放在路由表的最上方 path: '/', redirect: '/home' } ]
-
業務: 錯誤路由匹配,
const routes = [ { path: '/', redirect: '/home' //重定向 }, { path: '/home', component: Home }, { path: '/list', component: List }, { path: '/detail', component: Detail }, { path: '/login', component: Login }, { path: '/register', component: Register }, { path: '/user', component: User }, { path: '/shopcar', component: Shopcar }, { path: '/error', component: Error }, { //這個就是錯誤路由匹配, vue規定這個必須放在最下面,它必須將上面的路由全找一遍,找不到才用當前這個 path: '**', redirect: '/error' } ]
-
vue路由模式的確定 mode
-
如果你使用的是 hash , 那麼a標籤就可以了、
-
如果你使用 history , 那麼我們最好將a標籤改成 router-link 這個組件
- router-link 這個組件 身上必須要有一個 to 屬性
- router-link 這個組件身上加一個 keep-alive屬性可以進行瀏覽器緩存
-
二級路由
```javascript const routes = [ { path: '/shopcar', component: Shopcar, children: [ { path: 'pkq', //不寫 / component:Pkq } ] } ] ``` - 注意: 寫好配置之後,不要忘記了, 在對應的一級路由的組件中書寫 路由展示區域
- 命名路由
作用: 就是簡寫路徑了
{ path: '/shopcar', component: Shopcar, //子路由 children: [ { path: 'pkq', // 容易犯錯點 /pkq X component: Pkq, name: 'pkq' //命名路由 }, { path: 'gfly', component: Gfly } ] },
- 使用:
<router-link :to = "{name:'pkq'}"/>
- 使用:
-
思考: 有一個業務,當我們點擊 /mine的時候,要自動跳轉到 /mine/login,這個時候我們發現手段不夠用了,生命週期鉤子函數也實現不了,這個我們想,如果我們能監聽到路由的變化,那該有多好?
解決; vue爲了能夠監聽路由的變化情況,給了一個解決方法: 這個就是導航守衛
vue-router 進階
動態路由 & 路由傳參 & 路由接參
-
動態路由:
- url中路由是改變的,但是改變路由公用一個組件
- 舉例:
- localhost:3000/detail/001?a=1&b=2
- localhost:3000/detail/002?a=2&b=3
- detail
-
vue cli3 配置反向代理
- 在根目錄下面新建一個 vue.config.js
// vue.config.js中可以默認直接使用 http-proxy-middleware
module.exports = {
devServer: {
proxy: {
'/douban': { // /douban 是一個標記
target: 'http://api.douban.com', // 目標源
changeOrigin: true, // 修改源
pathRewrite: {
'^/douban': ''
}
},
'/siku': {
target: 'https://android.secoo.com',
changeOrigin: true,
pathRewrite: {
'^/siku': ''
}
}
}
}
}
- 路由的傳參
<router-link :to = "{name: 'list',params: {id: xxx}, query: {xxx:xxx}}"></router-link>
-
路由的接參
- 我們發現凡是使用了路由的組件,我們統稱爲: 路由組件
- 路由組件身上會自動添加一個 $route的數據
id: this.$route.params.id query: this.$route.query.xxx
-
編程式導航
- push
this.$router.push('/home')
- this.$router.push({name,params,query})
- push可以將我們的操作存放到瀏覽器的歷史記錄
- replace
- this.$router.replace(’/home’)
- this.$router.replace({name,params,query})
- replace沒有將我們的操作存放到瀏覽器的歷史記錄, 效果爲返回了二級
- push
-
業務:
- 按鈕的返回
- push
- replace
- back
- go
- 按鈕的返回
路由進階部分 – 導航守衛( 路由守衛 )
-
作用: — 類似 【保安】
- 守衛路由
- 進
- 舉例: 攜帶數據進
- 出
- 舉例: 事情完成才能出
- 進
- 守衛路由
-
導航守衛一共有三種形式
-
A: 全局導航守衛
- 全局前置守衛
router.beforeEach(fn)
- fn中有三個參數
- to
- from
- next
- true/false/’/login’/{ name: ‘login’}/ vm => {}
- 使用場景: 當我們本地存儲/cookie中有token,那我們就自動跳轉 /mine
- fn中有三個參數
- 全局的解析守衛
- 在 2.5.0+ 你可以用 router.beforeResolve 註冊一個全局守衛。這和 router.beforeEach 類似,區別是在導航被確認之前,同時在所有組件內守衛和異步路由組件被解析之後,解析守衛就被調用。
- 必須保證整個項目的守衛和異步路由組件解析完成
- 全局的後置守衛
- 可以做一些用戶友好提示
- 全局前置守衛
-
B: 路由獨享守衛 beforeEnter
- 寫在路由表中的守衛鉤子
- 針對的是和當前路由相關的,那麼其他與之不相關的路由,它是無法監聽它的變化情況的
-
C: 組件內守衛
- 組件內的前置守衛 beforeRouteEnter((to,from,next)=>{})
- 導航進入組件時,調用
- this是訪問不到的,如果非要訪問this ,必須通過 next(vm=>{})訪問
- 因爲組件此時沒有創建,所以沒有this
- 案例: 數據預載(進入組件前就獲得數據)
next(vm => { //vm指的就是組件 const result = JSON.parse(res.data.slice(7,-1)).rp_result.categorys vm.$set(vm.category,'categorys',result) })
- 組件內的後置守衛
- 當好離開組件時,調用
- this是可以訪問到 - 組件內的更新守衛( 路由傳參和路由的接參 )
- 在當前路由改變,但是該組件被複用時調用
- 舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
- 由於會渲染同樣的 Foo 組件,因此組件實例會被複用。而這個鉤子就會在這個情況下被調用。
- 可以訪問組件實例
this
- 組件內的前置守衛 beforeRouteEnter((to,from,next)=>{})
-
-
功能: 導航守衛可以監聽路由變化情況
-
名詞
- 前置: 要進入當前路由
- 後置: 要離開當前路由
-
關於next的使用
- next() 等價於 next( true ) 表示可以從當前路由跳轉到目標路由
- next( false ) 表示不通過, 表示從當前路由跳轉不到目標路由
- next(’/login’) 等價於 next({path:’/login’}) 跳轉指定的路由
- next(’/login’) 等價於 next({path:’/login’,params,query})
- next( fn ) 數據預載
-
業務: 當我們進入到一個項目的首頁時,但是當我們沒有註冊賬號時,它主動跳轉到了註冊/登錄頁
router.beforeEach((to,from,next)=>{
const name = localStorage.getItem('name')
if( name || to.path === '/login' ){
//如果有 / --> /home
next()
}else{
next('/login')
}
})
-
業務: 當進入mine頁面的時候, 要判斷用戶是否登錄,如果沒有登錄,跳轉登錄頁
-
路由導航守衛
- 3中類型 7個路由監聽鉤子
- 業務:
- 監聽整個項目的路由變化情況 全局的前置守衛
- 監聽某個路由的變化情況 路由的獨享守衛
- 監聽的路由組件的路由變化情況 組件內的導航守衛