Vue-router的使用姿式

雖然有不少router的相關文章了,可是那又怎麼樣,我就是要寫。javascript

歡迎來個人Vue技術羣交流:Vue887516034css

其實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

base

瀏覽器url的前綴,默認爲'/',若是設置爲'/some/',則運行項目,瀏覽器url都是'/some/...',不會對靜態文件的引用產生影響,通常寫網站都會有域名,均可以把域名指向某個服務器目錄,因此默認'/'便可,若是是寫公司內部後臺管理,那麼不必定會用域名,可能就是某個ip下的某個目錄,好比打包後的文件在111.22.33.44/admin,這個時候路由的配置匹配瀏覽器路徑的時候,會從這個/admin開始算,若是base仍是默認的/,那麼路由配置的routespath就要所有加上/admin/前綴,而且router-linkpush方法也要加上這個/admin,很麻煩,可是隻要設置base'/admin/',路由內部配置以及全部相關的方法均可以忽視服務器ip下的目錄名。這種狀況,一樣也要配置webpackpublicPath也爲/admin/,這裏不細說了。nginx

mode

這個太簡單了,一共三種模式,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;
}
複製代碼

routes

核心路由配置,官網講的很詳細,我就講幾個注意點,全部自定義的配置,例如是否須要鑑權或者對應的icon等,須要規範化的話都寫在meta對象中, 不規範的話 ,就和path同級咯,隨意玩,玩壞了我不背鍋。

path是必須指定的,name須要惟一,不是必須。

routes的配置遵循順序匹配,當url成功匹配,就不會再往下匹配,因此像403,404的頁面應當寫在最後。

alias別名的使用,當須要在指定router-view顯示某個組件,而且但願瀏覽器url是本身想要的語義時使用

redirect重定向,參數能夠是路徑,也能夠是對象(重定向到某個name),注意重定向是改變內容+改變url

scrollBehavior

這個滾動行爲,老實說,感受很蹩腳,本人基本沒有使用過,他控制的是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菜單

menu其實就是路由的導航,就是router-link,有不少小夥伴會另外建一個叫作menu.js的文件,而後模擬路由配置的結構去寫一個數組,而後根據這個文件遍歷生成dom,是否是有畫蛇添足的感受,而且當使用第三方的menu的ui組件時,這種靜態文件是沒有狀態 (當前訪問路由的對應menu高亮,刷新頁面或者輸入路由的url進入頁面會丟失高亮) 的。

menu有不少種狀況,

  1. 固定層級,好比固定2層,或者3層,通常後臺管理系統,固定層級較多,由於美觀,整潔。這種就比較方便了。template的dom結構也比較方便。
  2. 「個性」的產品經理,「定製化」的menu菜單,未知的層級,這裏就要用到render函數去寫dom。

固定層級

<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的時候,pushitem.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>
複製代碼

關於路由傳參

  1. params就如上面動態路由所講,只有經過路由配置的name跳轉,纔會生效,即便沒有使用動態路由,也能夠經過params傳參

這裏有注意點:

  • 若是使用動態路由,那麼在動態路由頁面刷新路由,params參數依然存在,

  • 若是沒有使用動態路由,params參數只在跳轉路由時有效,刷新頁面則會丟失params

  1. query參數,能夠經過pathname跳轉均可以傳參,而且參數會和ajaxget請求同樣,附加到瀏覽器的url上,刷新頁面依然保留

路由的懶加載

路由組件打包單獨的js,當訪問路由時,加載對應js文件,加快首頁加載時間,會增長項目的整體積。

  1. npmyarn安裝babel-plugin-syntax-dynamic-import
  2. .babelrcbabel.config.js配置
module.exports = {
    plugins:["syntax-dynamic-import"]
}
複製代碼
  1. 路由文件使用
// 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。有需求的移步官方文檔。

部分api

  1. .vue文件中this.$router是指掛載的路由實例,可使用push等方法。
  2. .vue文件中this.$route當前路由信息對象,包括pathquery等,只讀屬性。
  3. router.approuter所掛載的vue實例,能夠經過router.app.$options.store訪問vuex,前提是main.js中,要先引入vuex,後引入router,不然報錯。
  4. router.push()經常使用路由跳轉方法,參數爲{path?:string,name?:string,params?:object,query?:object},須要注意的是,push爲方法名,與數組沒有聯繫。
  5. router.replace()替換當前路由,參數和push一致,區別是替換當前路由,即點擊瀏覽器的返回,不會回到以前被替換的路由。
  6. router.go()router.back(),參數爲整數,前進或後退幾步。
  7. router.addRoutes()參數是須要符合routes配置的數據,動態添加路由配置到原有配置。

結束

有疑問或者講錯的能夠提出

tips:懂得分享才能走的更遠。

歡迎來個人Vue技術羣交流:Vue887516034

若是以爲對你有用,就打賞一下吧。

相關文章
相關標籤/搜索