- 什么是路由?
1、后端路由:早期會通過解析不同的URL,服務(wù)器找到對應(yīng)的資源,并渲染成頁面,最后將對應(yīng)的頁面返回給客戶端直接展示。
2、前端路由:前后端分離后,可以先通過靜態(tài)資源服務(wù)器拿到HTML+CSS+JS文件,然后在進入不同頁面的時候使用Ajax獲取API服務(wù)器上的數(shù)據(jù)資源,這樣最大的優(yōu)點就是前后端責任清晰,后端專注于數(shù)據(jù),前端專注于可視化,服務(wù)器壓力也比較小。
3、前端路由/SPA:
a、首先,對于單頁面應(yīng)用程序整個項目只有一個HTML,用戶一開始就獲取整個項目靜態(tài)資源。
b、SPA是在前端路由的基礎(chǔ)上又增加了一層前端路由,通過監(jiān)測href的數(shù)據(jù)來切換不同的組件,切換到的組件發(fā)起Ajax請求,最后在API服務(wù)器上拿到數(shù)據(jù)資源,看起來就像進入了新頁面一樣。
c、vue-router是通過hash來修改href并可以做到不刷新頁面。(href是一個棧儲存,先進后出)
備注:URL:
協(xié)議:// 主機:端口/路徑?查詢#哈希
scheme:// host:port/path?query#fragment
location.hash = '/home'
history.pushState({},'','/home') // HTML提供的方法
history.go(-1) // 復(fù)數(shù)后退,正數(shù)為前進,數(shù)字帶表步數(shù)
- 具體的使用方法:
// 安裝vue-router,并新建文件夾router->index.js
npm install vue-router --save
在index.js中配置路由項
import Vue from 'vue'
import VueRouter from 'vue-router'
import about from '@/components/about'
import home from '@/components/home'
use(VueRouter) // 安裝注入插件
routes = [
{
path: '/',
name: 'home',
component: home,
redirect: '/home' // 重定向
meta: { // 元數(shù)據(jù)(描述數(shù)據(jù)的數(shù)據(jù))
title: '首頁'
},
beforeEach: (to, form, next) => {}, // 路由獨享守衛(wèi)
children: [ // 嵌套子路由
{
path: '/',
component: isMessage
},
{
path: 'isMessage',
component: isMessage
},
{
path: 'isNew',
component: isNew
}
]
},
{
path: '/about/:aboutId', // 動態(tài)綁定路由
component: about,
meta: {
title: '關(guān)于'
},
},
{
path: '/shopList',
component: shopList,
meta: {
title: '商品',
},
}
]
// 創(chuàng)建router實例
const router = new VueRouter({
routes
})
// 前置守衛(wèi)(guard)
router.beforeEach((to, form, next) => {
window.document.title = to.matched[0].meta.title // 修改每個頁面的標題
next() // 必須調(diào)用,否則不生效
})
// 后置鉤子(hook)
router.afterEach((to, form) => {
console.log(to)
})
export default router // 導(dǎo)出實例
掛載到vue實例
// 在main.js中
import router from './router' // 導(dǎo)入
new Vue({
el: ''#app',
router,
render: h => h(App)
})
路由跳轉(zhuǎn)
<router-link to="/home" tag="button" replace>按鈕</router-link>
// tag指定渲染成什么樣的標簽,replace不會在history中留下記錄,無法回退
this.$router.push('/home')
this.$router.replace('/home') // 無痕瀏覽
this.$router.go('/home') // 接受一個整數(shù)作為參數(shù),在 history 記錄中向前后多少步
<router-link :to="'/about/'+aboutData" tag="button">關(guān)于</router-link>
// 動態(tài)頁面的跳轉(zhuǎn)aboutData在data中定義
<h3>{{$route.params.aboutId}}</h3>
// 在about頁面中用可以拿到在動態(tài)的URL
<keep-alive exclude='about'>
// exclude排除某個路由不緩存,include為緩存,使用頁面name屬性標記,多個狀態(tài)用逗號且不能使用空格
// 路由來回跳轉(zhuǎn)時,保持頁面不更新
<router-view/>
</keep-alive>
activated () { // 活躍狀態(tài)執(zhí)行函數(shù)
this.$router.push(this.path) // 在活躍狀態(tài)的時候直接進入到需要展示的路由
},
deactivated() { // 非活躍狀態(tài)執(zhí)行函數(shù)
console.log('deactivated')
},
// 以上兩個函數(shù)必須適應(yīng)keep-alive才會有效
beforeRouteLeave (to, from, next) {
this.path = this.$route.path // 離開頁面的時候記錄下用戶選擇的路由
next()
}
嵌套路由
<router-link to='/home/isMessage'>消息</router-link>
<router-link to='/home/isNew'>新聞</router-link>
<router-view/>
路由的懶加載:js的靜態(tài)資源按組件分包,用到時再發(fā)送請求
// import about from '@/components/about'
// import home from '@/components/home'
const about = () => import('@/components/about')
const home = () => import('@/components/home')
路由傳參
<router-link :to="{path:'/shopList',query:{userId: '9527'}}" tag="button"></router-link> // 傳參
<h3>{{$route.query.userId}}</h3> // 接收參數(shù)
// 函數(shù)跳轉(zhuǎn)
<button @click="listClick">商品</button>
listClick () {
this.$router.push({
path: '/shopList',
query: {
name: 'word'
}
})}
<h3>{{$route.query.name}}</h3> // 接收參數(shù)
組件內(nèi)守衛(wèi)
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應(yīng)路由被 confirm 前調(diào)用
// 不!能!獲取組件實例 `this`
// 因為當守衛(wèi)執(zhí)行前,組件實例還沒被創(chuàng)建
},
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,但是該組件被復(fù)用時調(diào)用
// 舉例來說,對于一個帶有動態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時候,
// 由于會渲染同樣的 Foo 組件,因此組件實例會被復(fù)用。而這個鉤子就會在這個情況下被調(diào)用。
// 可以訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導(dǎo)航離開該組件的對應(yīng)路由時調(diào)用
// 可以訪問組件實例 `this`
}
}