- vue路由安裝與基本使用
- vue嵌套路由
- vue動態路由(路由組件傳參)
- vue路由重定向和一些其餘的路由相關
- 官方手冊:https://router.vuejs.org/zh/
1、vue路由安裝與基本使用
在項目根文件夾下執行如下命令安裝vue-ruoter:html
vue add router
執行命令後會有如下提示:vue
這個提示是讓咱們配置router的實現模式(hash或者history),這個模式在後面的路由配置中能夠設置,只是這裏選擇的是默認的模式,若是後面的路由配置中不設置就是用這裏選擇的模式,y表示選擇history模式,n選擇hash模式,使用hash模式在後面的url中會多出#/。html5
安裝完成之後可在項目根目錄下看到新增了router.js文件和views文件夾。vue-router
到這裏有必要提一下路由是幹嗎的(有計算機網絡基礎的甚至大神者此地繞路),路由一詞是用來描述網絡數據傳輸端到端的網絡路徑範圍進程,簡單的說就是將數據從一個端口送到另外一個端口的路徑。而在vue項目中vue-router(路由)就是幫助vue應用找到資源並加載到頁面的路徑,而且不會觸發頁面總體刷新重載,而是實現局部刷新。vue-cli
這裏有兩個重要的點,在編寫代碼時遇到url和src不須要添加完整的資源路徑,而是經過vue-router來配置路徑;其二是不刷新頁面,其核心實現是經過hash值或者HTML5的History interface特性來實現。segmentfault
關於vue-router的實現原理能夠參考這篇博客:https://segmentfault.com/a/1190000014822765api
關於HTML5的History能夠參考這篇博客:https://www.cnblogs.com/roucheng/p/html5api.html瀏覽器
起步示例:網絡
1 //組件模板結構 2 <a href="/">home</a> 3 <a href="/about">about</a> 4 <router-view></router-view> 5 6 //入口js文件 7 import Router from 'vue-router' //導入路由插件 8 import Home from './views/Home' //導入子組件 9 import About from './views/About' //導入子組件 10 11 Vue.use(Router) 12 13 const myRouter = new Router({ //建立路由實例 14 routes:[ 15 { 16 path: '/', 17 component:Home 18 }, 19 { 20 path: '/about', 21 component:About 22 } 23 ], 24 mode: 'history' //配置路由模式,配置history後url上不會多出#/ 25 }) 26 27 new Vue({ 28 router: myRouter, //在vue示例中引入路由實例 29 render: h => h(App) 30 }).$mount('#app')
<a>標籤的href屬性的路徑指向路由實例的path屬性;app
路由實例中的component屬性指示路由path指向的組件;
結構文本中的<router-view>標籤標識經過路由配置的鏈接獲取的組件的加載位置(a標籤href獲取的路由實例配置的path指向的組件在這個標籤的位置上顯示);
vue實例中router指示配置的路由實例;
注:在上面的示例中雖然實現了vue路由的應用,可是使用的是<a>標籤來實現的跳轉,這樣的實現會致使再加載組件的時候會刷新整個頁面,因此再組件模板中須要使用vue提供的自定義標籤<router-link>來代替<a>標籤實現導航,才能真正的實現vue路由局部更新的效果,因此示例中的模板結構須要修改爲:
1 <router-link to="/">home</router-link> 2 <router-link to="/about">about</router-link> 3 <router-view></router-view>
1.使用data數據綁定:
1 <router-link :to="homeLink">home</router-link> 2 3 //在組件內些綁定數據 4 <script> 5 export default { 6 data(){ 7 return { 8 homeLink: '/' 9 } 10 } 11 } 12 </script>
2.經過vue實例的router實例的名稱綁定:
1 //:to屬性JSON數據會根據模板所在組件綁定的vue實例中的router中的name進行匹配 2 <router-link :to="{name:'about'}">about</router-link> 3 //在router實例中給每一個路由申明name屬性 4 const myRouter = new Router({ 5 routes:[ 6 { 7 path: '/', 8 name:'home', 9 component:Home 10 }, 11 { 12 path: '/about', 13 name: 'about', 14 component:About 15 } 16 ], 17 mode:'history' 18 })
將router實例從入口js文件中分離出來做爲獨立模塊,而後在入口js文件中引入模塊,再在vue實例上綁定這個引入的路由模塊:


1 --主入口組件中的模板與數據 2 <template> 3 <div id="app"> 4 <router-link :to="homeLink">home</router-link> 5 <router-link :to="{name:'about'}">about</router-link> 6 <router-view></router-view> 7 </div> 8 </template> 9 10 <script> 11 export default { 12 data(){ 13 return { 14 homeLink: '/' 15 } 16 } 17 } 18 </script> 19 20 --主入口js文件 21 import router from './router' //主入口js文件中引入路由模塊 22 new Vue({ 23 router:router, //綁定引入的路由模塊這裏單獨寫一個‘router’同等與‘router:router’ 24 render: h => h(App) 25 }).$mount('#app') 26 27 --router模塊 28 import Vue from 'vue' 29 import Router from 'vue-router' 30 import Home from './views/Home.vue' 31 import About from './views/About' 32 33 Vue.use(Router) 34 35 export default new Router({ 36 routes:[ 37 { 38 path: '/', 39 name:'home', 40 component:Home 41 }, 42 { 43 path: '/about', 44 name: 'about', 45 component:About 46 } 47 ], 48 mode:'history' 49 })
2、嵌套路由
在vue-cli搭建的項目中是基於模塊來構建項目,模塊化構建項目就必然會須要在各個模塊中應用到模塊化的導入導出,須要大量的路徑操做,並且組件之間還存在嵌套操做,須要追蹤組件鏈級關係,控制頁面局部刷新等一系列的操做。若是在每一個組件中去重複的作些工做一是會致使代碼冗餘,二是會致使難以維護,三是組件的鏈級關係很差處理。下面經過一些關鍵的代碼來演示嵌套路由的應用:
--src //src文件夾 ----components //組件文件夾 ------ChilComOne //嵌套子組件1文件夾 --------ChilComOne1.vue --------ChilComOne2.vue----Views //示圖文件夾:(這裏寫一級組件) ------ComOne.vue ------ComTwo.vue ----App.vue //主入口組件 ----main.js //主入口文件 ----router.js //路由管理器
主入口組件:
<template> <div id="app"> <div> <router-link to="/comOne">ComOne</router-link> <router-link :to="{name:'comTwo'}">ComTwo</router-link> </div> <router-view></router-view> </div> </template>
主入口文件:
1 import Vue from 'vue' 2 import App from './App.vue' 3 import router from './router' 4 new Vue({ 5 router, 6 render: h => h(App) 7 }).$mount('#app')
路由管理器:
1 import Vue from 'vue' 2 import Router from 'vue-router' 3 import ComOne from './views/ComOne.vue' 4 import ComTwo from './views/ComTwo.vue' 5 6 import ChilComOne1 from './components/chilComOne/ChilComOne1.vue' 7 import ChilComOne2 from './components/chilComOne/ChilComOne2.vue' 8 9 Vue.use(Router) 10 11 export default new Router({ 12 routes: [ 13 { 14 path: '/comOne', 15 name: 'comOne', 16 component: ComOne, 17 children:[ 18 { 19 path: '/comOne/one1', 20 name:'one1', 21 component: ChilComOne1 22 }, 23 { 24 path: '/comOne/one2', 25 name: 'one2', 26 component: ChilComOne2 27 } 28 ] 29 }, 30 { 31 path: '/comTwo', 32 name: 'comTwo', 33 component: ComTwo 34 } 35 ], 36 mode:"history" 37 })
子組件ComOne:
1 <template> 2 <div class="comOne"> 3 <div> 4 <router-link to="/comOne/one1">ChilComOne1</router-link> 5 <router-link to="/comOne/one2">ChilComOne2</router-link> 6 </div> 7 <router-view></router-view> 8 </div> 9 </template>
子組件ComTwo:
1 <template> 2 <div class="comTwo"> 3 我是comTwo 4 </div> 5 </template>
ComOne的子組件ChilComOne1:
1 <template> 2 <div class="one1"> 3 我是ChilComOne1 4 </div> 5 </template>
ComOne的子組件ChilComOne2:
<template>
<div class="one2"> 我是ChilComOne2 </div>
</template>
在示例中有一處代碼明顯合乎router的初衷,就是ComOne組件間模板中的次子組件的to屬性值應該不能是這樣寫:
<router-link to="/comOne/one1">ChilComOne1</router-link> <router-link to="/comOne/one2">ChilComOne2</router-link>
這樣的寫法雖然實現了咱們想要的效果,可是若是是在配置中重寫了路徑,這時候就必須到模板中作相應的更改,並且還在代碼中重複出現了父級組件的路由「/comOne」,更不符合router的配置初衷,這裏應該寫入name的鍵值對更符合配置初衷,否則你想一想這還指示兩級路由,若是在實際開發中出現十幾級的路由配置估計這個寫法會瘋掉,因此能夠改寫成下面這樣的代碼:
<router-link :to="{name:'one1'}">ChilComOne1</router-link> <router-link :to="{name:'one2'}">ChilComOne2</router-link>
這個寫法你會發現似曾相識,模板語法中的表達式,沒錯,這個小小的改動也是爲後面的動態路由作準備。
.router-link-exact-active .router-link-active
這兩個類名是由分別表示當前選中的路由連接元素、當前路由在url節點上的連接元素。好比用下面這個RUL來分析:
http://localhost:8081/comOne/one1
綁定「/comOne」和「/comOne/one1」的<router-link>會被路由管理器添加上router-link-active這個class值;而綁定「/comOne/one1」的<router-link>元素還會添加上router-link-exact-active這個class值,也就是被選中的當前元素的意思。主要被應用與導航按鈕,當前選中和在url路徑上的導航按鈕能夠依據這個類名來切換樣式。
這個類名還能夠在router實例中配置,使用自定義的類名:
//在router實例中配置 linkExactActiveClass:"exact", //與.router-link-exact-active相對應 linkActiveClass:"active" //與.router-link-active相對應
這樣配置後就能夠在樣式表中使用exact 和active 來設置樣式了。
多個組件普配同一個router-view是很是廣泛的現象,若是樣式不是經過數據來控制,而是直接寫在每一個組件的style內的話,這時候就會致使樣式衝突,解決這個文本很簡單:只須要在組件的style標籤上添加一個scoped空屬性就能夠實現每一個組件做用各自的樣式了。這個問題其實在vue的代碼片斷那篇博客我就已經解決了,在自動生成代碼片斷時我就已經設置了scoped屬性,若是你的代碼片斷模板中沒有配置能夠按照下面的方式手動添加,若是須要配置代碼片斷能夠參考這篇博客:https://www.cnblogs.com/ZheOneAndOnly/p/11213183.html
<style scoped></style>
3、vue動態路由(路由組件傳參)
路由傳參基本保持兩種方式,一種是基於路由的params的方式傳參,一種是基於組件的props屬性傳參方式。params主要仍是爲路由提供路徑參數,props則是路由爲組件提供參數。
關於params和props的傳參還有一個相互做用的應用,就是當props的值被設置爲booler值true時,會將經過params傳遞的參數轉換成props,在vue實例中一樣可使用props:[]來接收params中的key來獲取參數。並同時在$route.params中仍然能夠得到params完整的數據。
最後props還能夠是一個方法,這個方法能夠接收一個參數,這個參數就是$route,而後方法返回一個對象,與直接設置props爲一個對象的操做徹底一致,只是這裏爲咱們揭開了props轉換params的值的底層原理。
詳細內容能夠參考官方手冊:https://router.vuejs.org/zh/guide/essentials/passing-props.html
關於router傳參解析能夠參考這篇博客:https://blog.csdn.net/mapbar_front/article/details/79362602
1 //router-link組件模板代碼(僅展現關鍵實現代碼) 2 <router-link 3 tag="li" 4 :to="{ 5 name:'studentsPre', 6 params:{ 7 stuId:item.id, 8 stuClass:item.class 9 } 10 }" 11 v-for="item in studentsInfor" 12 :key="item.id" 13 ></router-link>
路由關鍵代碼:
1 { 2 path: '/studentsPre/:stuClass', 3 name:'studentsPre', 4 component:StudetsAddress, 5 props:true 6 }
經過params從router-link傳遞的stuClass實現路由的path參數動態切換,從而實現動態路由。
//接上面實例的代碼(StudetsAddress組件關鍵代碼) props:['stuId','stuClass']
所有代碼:
1 //文件結構 2 src 3 ----components 4 --------StudetsAddress.vue 5 ----views 6 --------Home.vue 7 -----App.vue 8 -----main.js 9 -----router.js


1 <template> 2 <div class="wrapper"> 3 <div class="head"> 4 <h2>成績系統</h2> 5 班級:{{stuClass}} 6 </div> 7 <ul> 8 <li> 9 <span class="stuId">學生編號</span> 10 <span class="stuName">學生姓名</span> 11 <span class="stuInfo">語文</span> 12 <span class="stuInfo">數學</span> 13 <span class="stuInfo">英語</span> 14 </li> 15 <li 16 v-for="item in stuClassList" 17 :key="item.id" 18 :class="{'assign':stuId == item.id}" 19 > 20 <span class="stuId">{{item.id}}</span> 21 <span class="stuName">{{item.name}}</span> 22 <span class="stuInfo">{{item.language}}</span> 23 <span class="stuInfo">{{item.math}}</span> 24 <span class="stuInfo">{{item.english}}</span> 25 </li> 26 </ul> 27 <router-view></router-view> 28 </div> 29 </template> 30 31 32 <script> 33 export default { 34 props:['stuId','stuClass'], 35 created(){ 36 this.stuAddressList.forEach(element => { 37 if(element.class == this.stuClass){ 38 this.stuClassList.push(element); 39 } 40 }); 41 }, 42 data(){ 43 return { 44 stuClassList:[], 45 stuAddressList:[ 46 { 47 id:'00001', 48 class:'001', 49 name:'張三', 50 language:86, 51 math:95, 52 english:91 53 }, 54 { 55 id:'00002', 56 class:'001', 57 name:'李四', 58 language:86, 59 math:95, 60 english:91 61 }, 62 { 63 id:'00003', 64 class:'001', 65 name:'王五', 66 language:86, 67 math:95, 68 english:91 69 }, 70 { 71 id:'00004', 72 class:'001', 73 name:'小明', 74 language:86, 75 math:95, 76 english:91 77 }, 78 { 79 id:'00005', 80 class:'001', 81 name:'小紅', 82 language:86, 83 math:95, 84 english:91 85 }, 86 { 87 id:'00006', 88 class:'002', 89 name:'小軍', 90 language:86, 91 math:95, 92 english:91 93 }, 94 { 95 id:'00007', 96 class:'002', 97 name:'小劉', 98 language:86, 99 math:95, 100 english:91 101 }, 102 { 103 id:'00008', 104 class:'002', 105 name:'小鄧', 106 language:86, 107 math:95, 108 english:91 109 }, 110 { 111 id:'00009', 112 class:'002', 113 name:'小強', 114 language:86, 115 math:95, 116 english:91 117 } 118 ] 119 } 120 } 121 } 122 </script> 123 124 <style scoped> 125 *{ 126 margin: 0px; 127 padding: 0px; 128 } 129 .wrapper{ 130 width: 100%; 131 } 132 .head,ul{ 133 width: 1000px; 134 margin: 0 auto; 135 background-color: #888; 136 } 137 li{ 138 list-style: none; 139 width: 100%; 140 height: 50px; 141 line-height: 50px; 142 border-bottom: 1px solid #000; 143 } 144 span{ 145 display: inline-block; 146 text-align: center; 147 } 148 .stuId{ 149 width: 100px; 150 } 151 .stuName{ 152 width:149px; 153 border-left: 1px solid #000; 154 } 155 .stuInfo{ 156 width: 249px; 157 border-left:1px solid #000; 158 } 159 .assign{ 160 background-color: #f00; 161 color: #fff; 162 } 163 </style>


1 <template> 2 <div id="home" class="warpper"> 3 <div class="head"> 4 <h2>學生信息表</h2> 5 </div> 6 <ul id="nav"> 7 <li> 8 <span class="stuId">學生編號</span> 9 <span class="stuName">名字</span> 10 <span class="stuAddress">地址</span> 11 <span class="stuClass">班級</span> 12 </li> 13 <!-- <router-link to="/">Home</router-link> | 14 <router-link to="/about">About</router-link> --> 15 <router-link 16 tag="li" 17 :to="{ 18 name:'studentsPre', 19 params:{ 20 stuId:item.id, 21 stuClass:item.class 22 } 23 }" 24 v-for="item in studentsInfor" 25 :key="item.id" 26 > 27 <span class="stuId">{{item.id}}</span> 28 <span class="stuName">{{item.name}}</span> 29 <span class="stuAddress">{{item.address}}</span> 30 <span class="stuClass">{{item.class}}</span> 31 </router-link> 32 </ul> 33 </div> 34 </template> 35 <script> 36 export default { 37 data(){ 38 return { 39 studentsInfor:[ 40 { 41 id:'00001', 42 class:'001', 43 name:'張三', 44 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 45 }, 46 { 47 id:'00002', 48 class:'001', 49 name:'李四', 50 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 51 }, 52 { 53 id:'00003', 54 class:'001', 55 name:'王五', 56 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 57 },{ 58 id:'00004', 59 class:'001', 60 name:'小明', 61 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 62 }, 63 { 64 id:'00005', 65 class:'001', 66 name:'小紅', 67 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 68 }, 69 { 70 id:'00006', 71 class:'002', 72 name:'小軍', 73 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 74 }, 75 { 76 id:'00007', 77 class:'002', 78 name:'小劉', 79 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 80 },{ 81 id:'00008', 82 class:'002', 83 name:'小鄧', 84 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 85 }, 86 { 87 id:'00009', 88 class:'002', 89 name:'小強', 90 address:"sdkfjlsdkjlfkjldsjlfkldsjlfjs" 91 } 92 ] 93 } 94 } 95 } 96 </script> 97 98 <style scoped> 99 *{ 100 margin: 0px; 101 padding: 0px; 102 } 103 .warpper{ 104 width: 100%; 105 /* background-color: #000; */ 106 } 107 .head{ 108 width: 1000px; 109 height: 150px; 110 margin: 0 auto; 111 border: 1px solid #f0f; 112 background-color: #888; 113 } 114 ul{ 115 width: 1000px; 116 margin: 0 auto; 117 } 118 li{ 119 list-style: none; 120 width: 998; 121 height: 50px; 122 border-right: 1px solid #000; 123 border-bottom: 1px solid #000; 124 border-left: 1px solid #000; 125 background-color: #888; 126 } 127 li span { 128 display: inline-block; 129 color: #fff; 130 line-height: 50px; 131 padding: 0 10px; 132 } 133 .stuId{ 134 width: 146px; 135 } 136 .stuName{ 137 width: 199px; 138 border-left: 1px solid #f0f; 139 } 140 .stuAddress{ 141 width: 399px; 142 border-left: 1px solid #f0f; 143 } 144 .stuClass{ 145 width: 149px; 146 border-left: 1px solid #f0f; 147 } 148 </style>


1 import Vue from 'vue' 2 import Router from 'vue-router' 3 import Home from './views/Home.vue' 4 5 import StudetsAddress from './components/StudetsAddress.vue' 6 7 Vue.use(Router) 8 9 export default new Router({ 10 mode: 'history', 11 base: process.env.BASE_URL, 12 routes: [ 13 { 14 path: '/home', 15 name: 'home', 16 component:Home 17 }, 18 { 19 path: '/studentsPre/:stuClass', 20 name:'studentsPre', 21 component:StudetsAddress, 22 props:true 23 } 24 ] 25 })


1 <template> 2 <div id="app"> 3 <router-link :to="{name:'home'}">home</router-link> 4 <router-view></router-view> 5 </div> 6 </template>


1 import Vue from 'vue' 2 import App from './App.vue' 3 import router from './router' 4 5 Vue.config.productionTip = false 6 7 new Vue({ 8 router, 9 render: h => h(App) 10 }).$mount('#app')
4、vue路由重定向與一些其餘路由相關
有時候當打開一個頁面時,除了加載當前路由的內容之外,還須要初始加載一個子路由數據做爲初始化頁面的內容,就能夠經過重定向到指定的路由:(路由屬性:redirect)
1 { 2 path: '/community', 3 name: 'community', 4 redirect:'/community/academic', //重定向到/community/academic 5 component: Community, 6 children: [ 7 { 8 path: '/community/academic', 9 name: 'academic', 10 component: Academic 11 } 12 ] 13 } 14 }
還有一些狀況就是出現修改瀏覽器上的url致使出現不存在的路由,致使沒法正確加載頁面,這時候能夠經過識別錯誤數據,可使用$router.go()方法來實現重定向,也可使用$router.replace()和$router.push()方法實現重定向跳轉。先來簡單的介紹如下這三個重定向方法的使用:
1.this.$router.push():跳轉到指定的url,這個方法會向history棧添加一個記錄,點擊後退到上一個頁面。
2.this.$router.replace():跳轉到指定的url,這個方法是在history棧中替換當前記錄,因此點擊放回是回退到上上個頁面。以前的頁面被這個跳轉頁面替換掉了,因此沒法回退到以前的頁面。
3.this.$router.go(n):相對當前頁面向前或向後跳轉多少個頁面,雷士window.history.go(n)。n能夠爲正負數,正數返回上一個頁面。負數按照history棧逐級向上跳轉。
這裏須要注意的是在我前面提出來的問題,當咱們使用這三個方法來解決錯誤路徑時,若是出現錯誤路徑就回到以前跳轉過來的頁面就可使用go(-1)來解決。若是要跳轉到提示錯誤路徑的頁面的話最好使用replace(err)來實現,由於replace使用的是替換錯誤路徑的棧,而push(err)是在history棧上添加一個新的err路徑,當使用瀏覽器的回退功能時,又會回到上一個錯誤路徑,致使檢測到錯誤後又進入錯誤提示頁面err。
1 created(){ 2 const questionId = this.$route.params.id; 3 const index = this.questionList.findIndex(item => item.questionId == questionId); 4 if(index == -1){//index爲-1時表示未得到正確的路由 5 // this.$router.go(-1); 6 // this.$router.push(err) 7 this.$router.replace({name:'err'}); 8 }else{ 9 this.question = this.questionList[index].title; 10 } 11 }
重定向除了以上的方法之外,還有一個動態返回重定向目標的方法retdirect(to),看代碼:
1 { 2 path: '*', 3 redirect(to){ 4 if(to.path == '/'){ 5 return '/home' //當經過網址登入時,重定向到‘/home’頁面(默認home首頁) 6 }else { 7 return {name : 'err'} //當出現沒法識別的路由時跳轉到錯誤提示頁面 8 } 9 } 10 }
配置多組件路由:
1 //router.js的配置 2 { 3 path: '/home', 4 name: 'home', 5 components: { //配置多組件路由時components是帶了s的複數 6 default: Home, //默認組件,在router-view中不配置name就會自動加載這個組件 7 'academic': Academic //配置自定義組件 8 } 9 } 10 11 //vue的結構 12 <router-view /> <!--匹配默認路由組件--> 13 <router-view name="academic"> <!--經過name匹配自定義路由組件academic-->
一般在配置子路由path的參數時,採用‘/’的配置方式就必須重最開始的父級寫到當前路由,路過路由嵌套到了十幾層呢?這個寫法絕對崩潰,簡寫的方式就是去掉'/'而後子須要寫當前路由節點的字段,router在解釋時會逐級添加父級路由和‘/’斜杆標識:(注:起始的第一個父級路由的斜杆‘/’不能省)
1 { 2 path: '/community', 3 ... 4 children: [ 5 { 6 path: '/community/academic', 7 ... 8 children: [ 9 { 10 path: '/community/academic/aaa', 11 } 12 } 13 ] 14 } 15 //簡寫方式 16 { 17 path: '/community', 18 ... 19 children: [ 20 { 21 path: 'academic', 22 ... 23 children: [ 24 { 25 path: 'aaa', 26 } 27 } 28 ] 29 }
1 { 2 path: '/home', 3 alias: '/b', //這時候訪問/b路由能夠一樣得到/home的組件,可是在rul中依然顯示的是/home 4 name: 'home', 5 component: Home 6 }
所謂別名嘛就是多個名字但指代的是同一我的,可是官方的展現的信息仍是官方認定的主名稱,這與路由別名是同一個道理。