Vue-Router 路由
一.路由簡介
1.後端路由
應用程序如果去處理不同的url地址發送過來的請求
post : localhost:3000/api/login
get: localhost:3000/api/getlist
2.前端路由
不同的url地址要渲染不同的頁面效果
- get: localhost:8080/index.html ()
- get: localhost:8080/index
- get: localhost:8080/#/index (hash模式路由)
後端路由與前端路由最本質的區別:前端只處理get請求
二.Vue-Router安裝使用
1.npm安裝
npm install vue-router -save-D
2.引用註冊路由
// 引入Vue
import Vue from 'vue';
//引入路由
import VueRouter from 'vue-router'
//註冊路由
Vue.use(VueRouter);
3.引入組件
//引入組件
import Index from './pages/Index.vue';
import Find from './pages/Find.vue';
import Mine from './pages/Mine.vue'
4.定義路由規則(是一個數組對象)
//定義路由規則
var routes = [
{
// path:路由url地址,一般是#後面的部分
// component:使用哪個路由頁面組件去渲染,
path: '/index',
component: Index
},
{
path: '/find',
component: Find
},
{
path: '/mine',
component: Mine
},
];
5.創建路由實例
//創建路由實例
let router = new VueRouter({
routes
});
6.在Vue實例配置router選項
var vm = new Vue({
el: "#app",
// 配置一個 router 選項
router,
});
//如果是模塊化構建的在main.js中配置
new Vue({
router,
render: h => h(App),
}).$mount('#app')
7.router-view 路由容器
<router-view></router-view>
路由視圖本身是VueRouter提供的一個全局的組件 router-view,當url地址與某個路由規則匹配時,就會將相應的路由頁面組件渲染到這個router-view上.比如:
get #/index index組件渲染路由視圖
get #/list list組件渲染路由視圖
注意,設置組件時,最好能設置組件的name屬性,給它一個名字,不然VueDevtools
8.router-link
與router-view一樣,都是引入vue-router之後提供的全局組件
router-link的作用就是實現路由的跳轉(url的跳轉),其實它本質上就是一個a標籤,我們推薦使用它而不是使用a標籤來跳轉
<router-link to="/index" tag="span" active-class='on'>首頁</router-link>
<router-link to="/find" tag="span" active-class='on'>發現</router-link>
<router-link to="/mine" tag="span" active-class='on'>我的</router-link>
- to 屬性是必須的。用來設置點擊時跳轉到哪裏
- tag屬性,指定最終渲染成那個html標籤
- active-class用於指定高亮樣式的類名
三.路由屬性
1.命名視圖
有時候想同時展示多個視圖,不是嵌套展示,比如創建一個佈局,有導航欄和主內容2個視圖,這個時候就可以使用命名視圖了.界面中可以擁有多個單獨命名的視圖,而不是隻有一個單獨的出口.注意:如果router-view沒有設置名字,那麼默認名字爲default.
// 引入需要渲染的組件
//@ 相當於當前代碼的絕對路徑,到src層級
import A from '@/components/home/A.vue';
import B from '@/components/home/B.vue';
import C from '@/components/home/C.vue';
// 定義路由規則
var routes = [
//命名視圖,給router-view命名,用三個命名視圖來加載三個組件
{
path: '/abc',
components: {
//aaa,bbb,ccc是命名視圖
aaa: A,
bbb: B,
ccc: C
}
}]
//視圖容器 命名的視圖
<router-view name="aaa"></router-view>
<router-view name="bbb"></router-view>
<router-view name="ccc"></router-view>
一個視圖使用一個組件渲染,對於多個同個路由,多個視圖就需要多個組件.配置路由時,components 需要帶上s
注意:使用路由之後,頁面渲染不出來,主要有2種原因
- 1.頁面中沒有提供 router-view
- 2.當前的url地址沒有與之匹配的路由規則處理
2.命名路由
命名路由,就是在設置路由規則的時候,提供一個name屬性
給“路徑-組件”的匹配關係取個名字.
這個屬性值,後續可以用來實現跳轉
// 定義路由規則
var routes = [{
//命名路由
name: 'find',
path: '/find',
component: Find
}]
如果 要跳轉到命名路由,可以在
<router-link :to="{name:'find'}" tag="span" active-class="on">發現</router-link>
3.路由模式
路由模式分爲hash模式和history模式.vue-router默認hash模式
hash模式與history模式的區別?
-
1.url地址表現不同,hash模式有#號,history模式沒有
-
2.實現原理不同
hash模式是通過改變hash值並監聽hashchange事件
history模式是基於最新的html5裏面的history相關的api進行的一些操作
window.history.pushState()
window.history.replaceState()
監聽history模式使用的是window.history.onpopState()事件
-
3.兼容性不同
1.hash模式都可以兼容
2.history模式只能兼容到IE10以上
-
history模式在部署上線之後會出現404找不到頁面這種問題,需要後端配置相關的處理纔行.而hash模式沒有這個問題
-
5.history模式時,重定向會有些問題,需要頁面的名字叫index.html纔行
面試中,可能面試官會問到,你之前的項目是用的什麼模式?爲什麼要用這種模式?
其實很好回答:就說之前用的默認hash模式,雖然說有個#不怎麼好看,不怎麼美觀,但是沒人管這種區別啊,默認的用就用了,如果說你覺得不好看,我可以改爲history模式啊,沒有了#號,只不過需要運維在上線部署的時候,給它一段配置就可以了.
//創建路由實例
let router = new VueRouter({
//指定路由模式,默認爲hash
mode: 'history',
routes
});
4.重定向
當你訪問某一個路徑時,自動跳轉到另一個路徑
var routes = [{
//重定向
path: '/abc',
// 直接定向到某個路由 也可以定向到路由的別名
//redirect: '/find'
//也可以是命名式的路由
redirect: {
name: 'find'
},
{
// 一般寫在最後,通配符,路由地址不存在,直接跳轉到首頁
path:'*',redirect: 'index'
}
}
5.別名
給路由規則中的path設置一個別名
路由規則中配置alias配置項
var routes = [{
name: 'find',
path: '/find',
alias: '/ab',
component: Find,
},
通過別名可以直接定位到path裏的路徑,一般路徑很長的時候,可以使用別名
6.二級路由(嵌套路由)
實際開發中,我們很多時候,會遇到二級路由,三級的比較少,二級足夠了
//引入商品模快組件
import Detail from '@/pages/goods/detail.vue';
import Good from '@/pages/goods/good.vue';
var routes = [{
path: '/find',
component: Find,
alias: '/ab',
children: [
{
path: 'good',
component: Good
},
{
path: 'detail',
component: Detail
}
]
}]
//在find組件中需要設置視圖容器
<router-view></router-view>
7.動態路由
路由規則中path選項的值形如 /good/:xxxx/:yyyy 這種就是動態路由
var routes = [{
//動態路由:冒號後面的id是個變量,在/detail對應的組件中使用 this.$route.params獲取動態id
//路由傳參:props開啓路由傳參,並且允許接收參數的那個組件使用props屬性來接收
path: '/detail/:id', component: Detail, props: true
}]
使用這兩種方式都可以傳參
- this.$route.params.id 獲取參數
- props屬性接收參數
一般的情況下,我們使用動態路由的情景很多,比如跳轉到詳情頁,那麼詳情頁是如果獲取到傳過去的數據的呢?
是通過this.$route的數據,this.$route 中記錄當前url的各種匹配關係,這個對象中有很多屬性
- path 路由路徑
- query 當前路由的?號傳遞過來的參數,是個對象,類似express中req.query獲取的數據
- params 當前路由的動態參數的傳遞,是個對象.類似express中req.params獲取的數據
- fullPath 當前路由的一個完整路徑,包含帶有?號參數的
- meta 當前路由的元信息,是個對象,是一開始定義路由規則的時候再meta配置中設置的內容
8.聲明式導航
一般用於直接跳轉,可以用聲明式的導航,比如類似側邊欄,或者底部tab導航 用router-link來控制路由跳轉
<router-link to="/index" tag="span" active-class="on">首頁</router-link>
<router-link to="/find" tag="span" active-class="on">發現</router-link>
<router-link to="/mine" tag="span" active-class="on">我的</router-link>
9.編程式導航
除了使用router-link創建a標籤來定義導航鏈接外,我們還可以藉助router的實例方法,通過編寫代碼來實現
也就是:通過js控制路由跳轉
說起編程式導航,我們就不得不講的一個vue-router的內置對選哪個:$router對象
當我們使用vue-router之後,在vue的原型上提供了一個$router對象,使用這個對象的一些方法來進行路由的跳轉
1.this.$router.push()
想要導航到不同的 URL,則使用 router.push 方法。這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器後退按鈕時,則回到之前的 URL。
-
1.就相當於普通的router-link
-
2.它的參數可以是:
字符串,要跳轉到的路由path
對象,對象中要配置path屬性
2.this.$router.replace()
跟 router.push 很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。
-
就相當於帶有 replace 屬性 的 router-link
-
它的參數可以是:
字符串,要跳轉到路由的path
對象,對象中配置 path 屬性
3.router的區別
- $route 是當前匹配的路由信息對象,可以通過他獲取一些當前路由的一些信息,比如params動態參數.vue將$route掛到了每個組件的data數據裏面.
- $router 就是new VueRouter() 生成的那個實例對象,vue將他掛載到了vue的原型上面,所有每個組件都通過訪問,然後使用來完成編程式導航的一些操作
4.push()和replate和router-link上的to屬性
三者傳遞參數爲對象時,對象有哪些屬性?
- path
- name
- query
- params 注意:params與path會產生衝突,請使用name和params結合使用
- meta
10.路由懶加載
打包構建應用時,包會非常大,全是一些些的組件,影響頁面的加載,官方給的解決方法是,把不同路由對應的組件分開成不同的代碼塊,然後當路由被訪問的時候,才加載對應組件,會比較高效
結合Vue的異步組件和webpack的代碼分割功能,可以輕鬆實現路由組件的懶加載.
1.把異步組件定義成一個返回promise的工廠函數
const Index=()=>Promise.reslove({
//組件的定義對象
});
2.在webpack2中,使用動態import語法來定義代碼分塊點
import('./Index.vue')
結合這兩點,結合起來是:
const Index=()=>import('./Index.vue')
在項目中這種寫法,不建議寫
// 同步加載組件的寫法,不建議這麼寫
// import Home from './pages/Home.vue'
// import Find from './pages/Find.vue'
// import User from './pages/User.vue'
// import Detail from './pages/Detail.vue'
通常我們需要這樣寫,使用路由懶加載
// 建議使用路由懶加載的寫法,以節省項目性能
const Home = ()=>import('./pages/Home.vue')
const Find = ()=>import('./pages/Find.vue')
const User = ()=>import('./pages/User.vue')
const Detail = ()=>import('./pages/Detail.vue')
const Cart = ()=>import('./pages/Cart.vue')