雖然有不少
router
的相關文章了,可是那又怎麼樣,我就是要寫。javascript
歡迎來個人Vue技術羣交流:887516034css
其實vuejs有一個叫作動態組件的東西,效果和路由有點類似,根據需求顯示不一樣的組件,可是在實際使用上,很小氣,就給人玩不爽,沒辦法像路由同樣編程式導航(push
,replace
),也沒有瀏覽器路徑的語義引導,動態組件更適合小規模的局部tab,給你們秀一波用法html
<template>
<div>
ul>li>tab1+tab2 @click="" <!-- >>>此處改變下面data中的tab值就能夠切換了 -->
<!-- 此處至關於router-link效果,雖然沒有瀏覽器的url引導,可是能夠本身寫麪包屑 -->
<component :is="tab"></component> <!-- 這裏就是router-view顯示區了 -->
</div>
</template>
<script> import tab1 from 'path/to/tab1.vue' //相比vue-router要引入不少文件 麻煩 import tab2 from 'path/to/tab2.vue' //其實vue-router也引入文件,可是在.vue文件裏面引入那麼多就很難看 export default { data(){ tab:'tab1' //默認顯示tab1 }, components:{ tab1, tab2 //es6語法 對象中,鍵值相同能夠這樣寫 } } </script>
複製代碼
咱們不提動態組件了,開始router了。經常使用的api,官網介紹的很詳細了。記得看官方教程,別忘了官方的apivue
不論是什麼路由的配置 仍是vuex的配置等等,都有相應的規範,在普通js文件,不按規範也不會怎麼樣,在ts文件,就會報錯了。前提是有興趣玩ts。java
// router/index.js
// 此處省略一堆 import
const router = new Router({
base:'/',
mode:'history',//default-->hash
routes:[],
scrollBehavior:()=>{
return {x:0,y:0}
}
})
複製代碼
其實配置很簡單,就這麼一點。webpack
瀏覽器url的前綴,默認爲'/'
,若是設置爲'/some/'
,則運行項目,瀏覽器url都是'/some/...'
,不會對靜態文件的引用產生影響,通常寫網站都會有域名,均可以把域名指向某個服務器目錄,因此默認'/'
便可,若是是寫公司內部後臺管理,那麼不必定會用域名,可能就是某個ip下的某個目錄,好比打包後的文件在111.22.33.44/admin
,這個時候路由的配置匹配瀏覽器路徑的時候,會從這個/admin
開始算,若是base仍是默認的/
,那麼路由配置的routes
的path
就要所有加上/admin/
前綴,而且router-link
和push
方法也要加上這個/admin
,很麻煩,可是隻要設置base
爲'/admin/'
,路由內部配置以及全部相關的方法均可以忽視服務器ip下的目錄名。這種狀況,一樣也要配置webpack
的publicPath
也爲/admin/
,這裏不細說了。nginx
這個太簡單了,一共三種模式,es6
hash
:瀏覽器會有‘#’符號,參考錨點效果,缺點很醜,可是兼容性棒棒web
history
:去除‘#’符號,讓url變好看,下面會講服務端配置。ajax
abstract
:非瀏覽器環境,會強制使用這個模式,例如weex
history模式服務端配置
我我的和公司都是用nginx
,這裏就講nginx
,配置這個的緣由是當你進入某個路由以後,再次刷新頁面時(或者是瀏覽器直接輸入某個路由路徑時),當刷新頁面,瀏覽器就會從新dns解析,tcp協議,這個時候會根據瀏覽器的url去服務器找對應資源,固然咱們vue-router
是爲單頁面服務的,對應的url在服務端是確定沒有靜態資源的,就會出現404,當配置瞭如下url重寫語句,注意是重寫,不是重定向,不改變url的狀況重寫瀏覽器內容,重寫到index.html
,由於這個index.html
使咱們項目的入口,index.html
裏面會讀取當時打包好的app.js
,就能夠讀取到路由配置,以實現咱們瀏覽器的url對應的路由頁面。
hash
模式不須要配置,由於瀏覽器會忽略#和?後面的參數
打包文件在根目錄時,
location / {
try_files $uri $uri/ /index.html;
}
複製代碼
打包文件在非根目錄時,
location /admin {
try_files $uri $uri/ /admin/index.html;
}
複製代碼
核心路由配置,官網講的很詳細,我就講幾個注意點,全部自定義的配置,例如是否須要鑑權或者對應的icon等,須要規範化的話都寫在meta
對象中, 不規範的話 ,就和path
同級咯,隨意玩,玩壞了我不背鍋。
path
是必須指定的,name
須要惟一,不是必須。
routes
的配置遵循順序匹配,當url成功匹配,就不會再往下匹配,因此像403,404
的頁面應當寫在最後。
alias
別名的使用,當須要在指定router-view
顯示某個組件,而且但願瀏覽器url是本身想要的語義時使用
redirect
重定向,參數能夠是路徑,也能夠是對象(重定向到某個name),注意重定向是改變內容+改變url
這個滾動行爲,老實說,感受很蹩腳,本人基本沒有使用過,他控制的是body的滾動, 不少需求都是局部滾動。若是的確是須要控制body滾動,參考官方文檔便可。
路由的配置一開始只有根目錄/
,每寫一層children
就要寫一層router-view
,不然組件不顯示。每個嵌套children
的層級和router-view
的層級都是一一對應的。
// router/index.js
const router = new Router({
routes:[
{
path:'/', //此時配置數組的第一層級,即對應app.vue中的router-view
component:Home,// <<<----------------------------
children:[// |
{ // |
//此時第一層級出現children第二層級,------------
//那麼在這個第二層級所屬的第一層級 Home組件中,就要寫一層router-view,以此類推
path:'user',
component:User,
}
]
}
]
})
複製代碼
menu其實就是路由的導航,就是router-link,有不少小夥伴會另外建一個叫作menu.js的文件,而後模擬路由配置的結構去寫一個數組,而後根據這個文件遍歷生成dom,是否是有畫蛇添足的感受,而且當使用第三方的menu的ui組件時,這種靜態文件是沒有狀態 (當前訪問路由的對應menu高亮,刷新頁面或者輸入路由的url進入頁面會丟失高亮) 的。
menu有不少種狀況,
固定層級
<template>
<div class="menu">
<div class="first-menu" v-for="item,index in menus" :key="item.name">
<router-link :to="item.name">{{ item.meta.zhName }}</router-link>
<template v-if="item.children.length">
<div class="sub-menu" v-for="subItem.subIndex in item.children" :key="subItem.name">
<img :src="subItem.meta.icon" />
<router-link :to="subItem.name">
{{subItem.meta.zhName}}
</router-link>
</div>
</template>
</div>
</div>
</template>
<script> export default { computed:{ menus(){ return this.$router.options.routes //獲取路由配置 } } } </script>
<style> .router-link-active{ /* 激活樣式 */ } </style>
複製代碼
這裏我只寫了2層,而且沒有寫樣式,若是使用了像element-ui這樣的menu組件,他底層沒有渲染成router-link
,那就要編程式導航了,click
的時候,push
到item.name
,而且當前路由的導航樣式須要根據$route.name(當前路由配置)
來判斷
未知層級
由於不知道是幾層菜單,因此在template的html標籤沒辦法自由的遍歷,因此須要js去操做路由配置的遞歸,由於render函數式js操做,因此須要用render函數渲染。
<script> export default { computed:{ menus(){ return this.$router.options.routes //獲取路由配置 } }, // 使用render函數就不須要寫template標籤的dom了 render(h){ //這個 h 參數,原來的語義是createElement ,這裏使用 h 是方便操做,也是官方建議 // ...... 這裏是操做 menus 的遞歸代碼,再經過render函數循環出來 return h('div','這是一個div') //這裏必須return 對應的語法 } } </script>
複製代碼
render函數的語法參見官方文檔便可 render函數。
這裏有個注意點,若是
router
作了權限控制,那麼路由配置不能經過$router.options.routes
獲取,由於addRoutes
方法不改變原先的配置,須要在addRoutes
的同時,把完整的路由配置保存在vuex
,再獲取。權限控制不細講了,有不少相關文章,可是不建議copy,建議加入本身的理解,沒有絕對的方案。
過渡動畫應該都用了,通常使用opacity
過渡一下。
<template>
<transition mode="out-in" name="fade">
<!-- 這裏若是在行內直接用$route.meta去v-if判斷緩存 dom結構會變複雜 -->
<keep-alive :include="aliveRoutes">
<router-view :key="$route.fullPath" />
<!-- 此處經過路由的完整路徑加上key,當爲動態路由時,觸發路由組件從新渲染 -->
</keep-alive>
</transition>
<!-- 都是些官方用法 不細說了-->
</template>
<script> export default { computed:{ aliveRoutes(){ // this.$router.options.routes 獲取路由配置 //能夠配置meta 是否緩存 根據 meta 字段 push到數組裏 return [/* ... */] } } } </script>
複製代碼
官網講的超詳細的。觸發順序也講清楚了,官方的說法叫導航守衛。
注意點:要搞清楚哪些是全局鉤子,哪些是組件內的鉤子。而且全部的前置鉤子,須要調用next() 纔會正常進入路由,在寫鉤子函數內部邏輯時,須要注意,不能造成死循環
例如
router.beforeEach((to,from,next)=>{
if (from.name === 'login'){
next({
name:'login' //死循環
})
//更多next回調方法能夠查看官方文檔
}
})
複製代碼
組件內鉤子使用狀況,要看業務需求,好比動態路由↓↓↓。
動態路由,使用場景是一個固定的路由視圖組件,配合一個動態的瀏覽器url,在視圖中顯示不一樣的數據,同時但願url中有當前詳情的語義,例如詳情頁,用戶信息頁。
先看下路由如何配置動態,這裏用詳情頁舉例
// router/index.js
const router = new Router({
routes:[
{
path:'/list',
name:'list',
component:List
},
{
path:'/detail/:id',//此處id對應params.id
name:'detail',
component:Detail
}
]
})
複製代碼
<!-- List.vue -->
<template>
<div>
<ul>
<li @click="goDetail(item.id)" v-for="item in someData" :key="item.id">
</li>
</ul>
</div>
</template>
<script> export default{ methods:{ goDetail(_id){ this.$router.push({ name:'detail', //此處注意只有經過name跳轉路由,params纔會生效 //query不受影響 params:{ id:_id //此處對應routes配置的/:id } }) } } } </script>
複製代碼
<!-- Detail.vue -->
<script> export default { beforeRouteEnter (to, from, next) { //此處爲路由組件內的鉤子,能夠經過判斷 to.params.id 是否 undefined, //進行一些操做,由於即便 to.params.id 是 undefined,路由也能匹配成功 //由於這些id多是用來獲取數據的,不會在頁面顯示,不必定能察覺是 undefined } } </script>
複製代碼
關於路由傳參
params
就如上面動態路由所講,只有經過路由配置的name
跳轉,纔會生效,即便沒有使用動態路由,也能夠經過params
傳參這裏有注意點:
若是使用動態路由,那麼在動態路由頁面刷新路由,params
參數依然存在,
若是沒有使用動態路由,params
參數只在跳轉路由時有效,刷新頁面則會丟失params
query
參數,能夠經過path
或name
跳轉均可以傳參,而且參數會和ajax
的get
請求同樣,附加到瀏覽器的url上,刷新頁面依然保留路由組件打包單獨的js,當訪問路由時,加載對應js文件,加快首頁加載時間,會增長項目的整體積。
npm
或yarn
安裝babel-plugin-syntax-dynamic-import
.babelrc
或babel.config.js
配置module.exports = {
plugins:["syntax-dynamic-import"]
}
複製代碼
// router/index.js
const router = new Router({
routes:[
{
path:'/list',
name:'list',
component:()=>import(/* webpackChunkName:"SOME_NAME" */'path/to/List.vue')
//此處 import 是方法 和 es6 的 import 不同
//特殊註釋語法 相同chunkName 打包到一個js中 可省略
}
]
})
複製代碼
我歷來沒用到過命名視圖,不給你們誤導了,我能解釋的就是命名視圖的做用是一個瀏覽器url,匹配多個router-view
。有需求的移步官方文檔。
.vue
文件中this.$router
是指掛載的路由實例,可使用push
等方法。.vue
文件中this.$route
當前路由信息對象,包括path
,query
等,只讀屬性。router.app
指router
所掛載的vue
實例,能夠經過router.app.$options.store
訪問vuex
,前提是main.js
中,要先引入vuex
,後引入router
,不然報錯。router.push()
經常使用路由跳轉方法,參數爲{path?:string,name?:string,params?:object,query?:object}
,須要注意的是,push
爲方法名,與數組沒有聯繫。router.replace()
替換當前路由,參數和push
一致,區別是替換當前路由,即點擊瀏覽器的返回,不會回到以前被替換的路由。router.go()
和router.back()
,參數爲整數,前進或後退幾步。router.addRoutes()
參數是須要符合routes
配置的數據,動態添加路由配置到原有配置。有疑問或者講錯的能夠提出
tips:懂得分享才能走的更遠。
歡迎來個人Vue技術羣交流:887516034
若是以爲對你有用,就打賞一下吧。