> ??由于Vue在開發時對路由支持的不足,于是官方補充了vue-router插件。vue的單頁面應用是基于路由和組件的,路由用于設定訪問路徑,并將路徑和組件映射起來。傳統的頁面應用,是用一些超鏈接來實現頁面切換和跳轉的。在vue-router單頁面應用中,則是路徑之間的切換,實際上就是組件的切換。路由就是SPA(單頁應用)的路徑管理器。再通俗的說,vue-router就是我們WebApp的鏈接路徑管理系統。
> ??有的小伙伴會有疑慮,為什么我們不能像原來一樣直接用a標簽編寫鏈接呢?因為我們一般用Vue做的都是單頁應用,只有一個主頁面index.html,所以你寫的標簽是不起作用的,要使用vue-router來進行管理。
### 一、安裝
如果你用vue-cli腳手架來搭建項目,配置過程會選擇是否用到路由(詳細見我上一篇簡書),如果選擇y,后面下載依賴會自動下載vue-router。
這里還是說一下安裝:`npm install vue-router`
### 二、創建組件
如果在一個模塊化工程中使用它,必須要通過 Vue.use() 明確地安裝路由功能,用vue-cli生產了我們的項目結構,**src文件目錄下會有一個router文件夾**,此處就是編寫路由組件的地方。在src/router/index.js,這個文件就是路由的核心文件:
~~~jsx
import Vue from 'vue' //引入Vue
import Router from 'vue-router' //引入vue-router
import Hello from '@/components/Hello' //引入根目錄下的Hello.vue組件
Vue.use(Router) //Vue全局使用Router
export default new Router({
routes: [ //配置路由,這里是個數組
{ //每一個鏈接都是一個對象
path: '/', //鏈接路徑
name: 'Hello', //路由名稱,
component: Hello //對應的組件模板
},{
path:'/hi',
component:Hi,
children:[ //子路由,嵌套路由 (此處偷個懶,免得單獨再列一點)
{path:'/',component:Hi},
{path:'hi1',component:Hi1},
{path:'hi2',component:Hi2},
]
}
]
})
~~~
### 三、router-link制作導航
**1.router-link** 是一個組件,它默認會被渲染成一個帶有鏈接的a標簽,通過to屬性指定鏈接地址。
注意:被選中的router-link將自動添加一個class屬性值.router-link-active。
~~~xml
<router-link to="/">[text]</router-link>
~~~
* to:導航路徑,要填寫的是你在router/index.js文件里配置的path值,如果要導航到默認首頁,只需要寫成 to="/" ,
* \[text\] :就是我們要顯示給用戶的導航名稱。
**2.router-view** 用于渲染匹配到的組件。
①.可以給router-view組件設置**transition過渡**([Vue2.0 Transition常見用法全解惑](https://link.jianshu.com?t=http%3A%2F%2Fhyuhan.com%2F2016%2F12%2F08%2Fvue-transition%2F))。
~~~xml
<transition name="fade">
<router-view ></router-view>
</transition>
~~~
**css過渡類名:**
組件過渡過程中,會有四個CSS類名進行切換,這四個類名與transition的name屬性有關,比如name="fade",會有如下四個CSS類名:
* fade-enter:進入過渡的開始狀態,元素被插入時生效,只應用一幀后立刻刪除。
* fade-enter-active:進入過渡的結束狀態,元素被插入時就生效,在過渡過程完成后移除。
* fade-leave:離開過渡的開始狀態,元素被刪除時觸發,只應用一幀后立刻刪除。
* fade-leave-active:離開過渡的結束狀態,元素被刪除時生效,離開過渡完成后被刪除。
從上面四個類名可以看出,**fade-enter-active**和**fade-leave-active**在整個進入或離開過程中都有效,所以CSS的transition屬性在這兩個類下進行設置。
**過渡模式mode:**
* in-out(mode默認in-out模式):新元素先進入過渡,完成之后當前元素過渡離開。
* out-in:當前元素先進行過渡離開,離開完成后新元素過渡進入。
②.還可以配合`<keep-alive>`使用,**keep-alive**可以緩存數據,這樣不至于重新渲染路由組件的時候,之前那個路由組件的數據被清除了。比如對當前的路由組件a進行了一些DOM操作之后,點擊進入另一個路由組件b,再回到路由組件a的時候之前的DOM操作還保存在,如果不加keep-alive再回到路由組件a時,之前的DOM操作就沒有了,得重新進行。如果你的應用里有一個購物車組件,就需要用到keep-alive。
~~~xml
<transition>
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition>
~~~
### 四、動態路由匹配
我們經常需要把某種模式匹配到的所有路由,全都映射到同個組件。
調用router的map方法映射路由,每條路由以key-value的形式存在,key是路徑,value是組件。例如:'/home'是一條路由的key,它表示路徑;{component: Home}則表示該條路由映射的組件:
~~~go
router.map({
'/home': { component: Home },
'/about': { component: About }
})
~~~
例如,我們有一個 User 組件,對于所有 ID 各不相同的用戶,都要使用這個組件來渲染。那么,我們可以在 vue-router 的路由路徑中使用『動態路徑參數』來達到這個效果。
~~~csharp
const User = {
template: '<div>User</div>'
}
const router = new VueRouter({
routes: [
// 動態路徑參數 以冒號開頭
{ path: '/user/:id', component: User }
]
})
~~~
例如: /user/foo 和 /user/bar 都將映射到相同的路由。
一個『路徑參數』使用冒號 : 標記。當匹配到一個路由時,參數值會被設置到**this.$route.params**,可以在每個組件內使用。
你可以在一個路由中設置多段『路徑參數』,對應的值都會設置到 **$route.params** 中。例如:

### 五、vue-router參數傳遞
##### 1.用name傳值(不推薦)

##### 2.通過 標簽中的to傳參
~~~xml
<router-link :to="{name:‘dxl’,params:{key:value}}">東西里</router-link>
~~~
* name:就是我們在路由配置文件中起的name值。
另:**命名路由**就是用一個名稱來標識一個路由,在定義路由的時候設置一個name屬性即可。**在router-link中也可以用路由的名字來鏈接到一個路由。**
* params:就是我們要傳的參數,它也是對象形勢,在對象里可以傳遞多個值。
最后用`$route.params.username`進行接收.
##### 3.用url傳參
上面第五點也有提到。 **:冒號的形式傳遞參數**
(1).在router路由配置文件里以冒號的形式設置參數
~~~undefined
{
path:'/params/:newsId/:userName,
component:Params
}
~~~
(2).組件形式,在src/components目錄下建立我們params.vue組件。
我們在頁面里輸出了url傳遞的參數。
~~~xml
<template>
<div>
<h2>{{ msg }}</h2>
<p>新聞ID:{{ $route.params.newsId}}</p>
<p>用戶名:{{ $route.params.userName}}</p>
</div>
</template>
<script>
export default {
name: 'params',
data () {
return {
msg: 'params page'
}
}
}
</script>
~~~
(3).標簽path路徑中傳值
~~~undefined
<router-link to="/params/888/dxl shuai>params</router-link>
~~~
(4).正則表達式在URL傳值中的應用
希望我們傳遞的新聞ID只能是數字的形式,這時候我們就需要在傳遞時有個基本的類型判斷,`path:'/params/:newsId(\\d+)/:userName'`
### 六.響應路由參數的變化
當使用路由參數時,例如從 /user/foo 導航到 /user/bar,原來的組件實例會被復用。因為兩個路由都渲染同個組件,比起銷毀再創建,復用則顯得更加高效。不過,這也意味著組件的生命周期鉤子不會再被調用。
復用組件時,想對路由參數的變化作出響應的話:
(1). watch(監測變化) $route 對象:
~~~csharp
const User = {
template: '...',
watch: {
'$route' (to, from) {
// 對路由變化作出響應...
}
}
}
~~~
(2).beforeRouteUpdate 導航守衛
如果目的地和當前路由相同,只有參數發生了改變 (比如從一個用戶資料到另一個 `/users/1` -> `/users/2`),你需要使用 `beforeRouteUpdate`來響應這個變化 (比如抓取用戶信息)。
~~~csharp
const User = {
template: '...',
beforeRouteUpdate (to, from, next) {
// react to route changes...
// don't forget to call next()
}
}
~~~
### 七、實現不同路由不同頁面標題
~~~jsx
// 定義路由的時候如下定義,name也可為中文
const routes = [
{ path: '/goods', component: goods, name: 'goods' },
{ path: '/orders', component: orders, name: 'orders' },
{ path: '/seller', component: seller, name: 'seller' }
];
// 創建路由實例
const router = new VueRouter({
routes: routes
})
// 關鍵在這里,設置afterEach鉤子函數
router.afterEach((to, from, next) => {
document.title = to.name;
})
~~~
### 八、重定向
剛進入應用都是進入到“/”這個路由的,如果想直接進入到“/goods”怎么辦,有兩種方法。一種是利用重定向,另一種是利用vue-router的導航式編程。
redirect基本重定向:
~~~csharp
const routes = [
{ path: '/', redirect: '/goods'}
]
重定向的目標也可以是一個命名的路由。
const routes = [
{ path: '/', redirect: { name: 'goods' }}
]
重定向時也可以傳遞參數
{
path:'/',
redirect:'/goods/:newsId(\\d+)/:userName'
}
~~~
★.這里不得不提到**alias**別名的使用。
1.首先我們在路由配置文件里給路徑起一個別名,dxl。
~~~css
{
path: '/hi',
component: Hi,
alias:'/dxl'
}
~~~
2.配置我們的,起過別名之后,可以直接使用標簽里的to屬性,進行重新定向。
~~~xml
<router-link to="/dxl">jspang</router-link>
~~~
區別:
* redirect:仔細觀察URL,redirect是直接改變了url的值,把url變成了真實的path路徑。
* alias:URL路徑沒有別改變,這種情況更友好,讓用戶知道自己訪問的路徑,只是改變了中的內容。
★★★.注意一個大坑:
**別名alias在path為'/'中,是不起作用的。**
~~~css
{
path: '/',
component: Hello,
alias:'/home'
}
~~~
### 九、編程式導航
**1.router.push( )**
想要導航到不同的 URL,則使用 **router.push (在創建vue實例并掛載后調用)**。router.push方法就是用來動態導航到不同的鏈接的,這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器后退按鈕時,則回到之前的 URL。
當你點擊 時,這個方法會在內部調用,所以說,點擊 等同于調用 router.push(...)。

**注意:
如果提供了 path,params 會被忽略,而 query 并不屬于這種情況。取而代之的是下面例子的做法,你需要提供路由的 name 或手寫完整的帶有參數的 path:**
~~~csharp
const userId = 123
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 這里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
~~~
**2.router.replace( )**
router.replace跟 router.push 很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。

**3.router.go(n)**
這個方法的參數是一個整數,意思是在 history 記錄中向前或者后退多少步,類似 window.history.go(n)。
~~~go
// 在瀏覽器記錄中前進一步,等同于 history.forward()
router.go(1)
// 后退一步記錄,等同于 history.back()
router.go(-1)
~~~
自定義一個goback()方法,并使用this.$router.go(-1),進行后退操作
~~~xml
<script>
export default {
name: 'app',
methods:{
goback(){
this.$router.go(-1);
},
goHome(){
this.$router.push('/');
}
}
}
</script>
~~~
### 十、路由中的鉤子
**1.路由配置文件中的鉤子函數:**
在路由文件中我們只能寫一個beforeEnter,就是在進入此路由配置時:
~~~jsx
{
path:'/params/:newsId(\\d+)/:userName',
component:Params,
beforeEnter:(to,from,next)=>{
console.log('我進入了params模板');
console.log(to);
console.log(from);
next();
},
~~~
三個參數:
* to:路由將要跳轉的路徑信息,信息是包含在對像里邊的。
* from:路徑跳轉前的路徑信息,也是一個對象的形式。
* next:路由的控制參數,常用的有next(true)和next(false)。
**2.寫在模板中的鉤子函數:**
寫在模板中就可以有兩個鉤子函數可以使用。
beforeRouteEnter:在路由進入前的鉤子函數。
beforeRouteLeave:在路由離開前的鉤子函數。
~~~jsx
export default {
name: 'params',
data () {
return {
msg: 'params page'
}
},
beforeRouteEnter:(to,from,next)=>{
console.log("準備進入路由模板");
next();
},
beforeRouteLeave: (to, from, next) => {
console.log("準備離開路由模板");
next();
}
}
~~~
★此處常用于**數據獲取**。
* **導航完成之后獲取**:先完成導航,然后在接下來的組件生命周期鉤子中獲取數據。在數據獲取期間顯示『加載中』之類的指示。
當你使用這種方式時,我們會馬上導航和渲染組件,然后在組件的 **created** 鉤子中獲取數據。這讓我們有機會在數據獲取期間展示一個 loading 狀態,還可以在不同視圖間展示不同的 loading 狀態。
假設我們有一個 Post 組件,需要基于 `$route.params.id` 獲取文章數據:
~~~kotlin
<template>
<div class="post">
<div class="loading" v-if="loading">
Loading...
</div>
<div v-if="error" class="error">
{{ error }}
</div>
<div v-if="post" class="content">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
</div>
</template>
export default {
data () {
return {
loading: false,
post: null,
error: null
}
},
created () {
// 組件創建完后獲取數據,
// 此時 data 已經被 observed 了
this.fetchData()
},
watch: {
// 如果路由有變化,會再次執行該方法
'$route': 'fetchData'
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
// replace getPost with your data fetching util / API wrapper
getPost(this.$route.params.id, (err, post) => {
this.loading = false
if (err) {
this.error = err.toString()
} else {
this.post = post
}
})
}
}
}
~~~
* **導航完成之前獲取**:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功后再執行導航。
通過這種方式,我們在導航轉入新的路由前獲取數據。我們可以在接下來的組件的 beforeRouteEnter 守衛中獲取數據,當數據獲取成功后只調用 next 方法。
~~~tsx
export default {
data () {
return {
post: null,
error: null
}
},
beforeRouteEnter (to, from, next) {
getPost(to.params.id, (err, post) => {
next(vm => vm.setData(err, post))
})
},
// 路由改變前,組件就已經渲染完了
// 邏輯稍稍不同
beforeRouteUpdate (to, from, next) {
this.post = null
getPost(to.params.id, (err, post) => {
this.setData(err, post)
next()
})
},
methods: {
setData (err, post) {
if (err) {
this.error = err.toString()
} else {
this.post = post
}
}
}
}
~~~
### 十一、History 模式
vue-router 默認 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,于是當 URL 改變時,頁面不會重新加載。
如果不想要很丑的 hash,我們可以用路由的 history 模式,這種模式充分利用 history.pushState API 來完成 URL 跳轉而無須重新加載頁面。
~~~csharp
const router = new VueRouter({
mode: 'history',
routes: [...]
})
~~~
在學習過渡效果的時候,我們學了mode的設置,但是在路由的屬性中還有一個mode。
**mode的兩個值:**
* histroy:當你使用 history 模式時,URL 就像正常的 url,[http://www.dxl.com/user/id](https://link.jianshu.com?t=http%3A%2F%2Fwww.dxl.com%2Fuser%2Fid)
不過這種模式要玩好,還需要后臺配置支持。因為我們的應用是個單頁客戶端應用,如果后臺沒有正確的配置,當用戶在瀏覽器直接訪問 [http://www.dxl.com/user/id](https://link.jianshu.com?t=http%3A%2F%2Fwww.dxl.com%2Fuser%2Fid)就會返回 404,。所以要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。

這么做以后,你的服務器就不再返回 404 錯誤頁面,因為對于所有路徑都會返回 index.html 文件。**為了避免這種情況,你應該在 Vue 應用里面覆蓋所有的路由情況,然后在給出一個 404 頁面。**
~~~jsx
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '*', component: Error}
]
})
~~~
這里的path:'\*'就是找不到頁面時的配置,component是我們新建的一個Error.vue的文件
* hash:默認’hash’值,但是hash看起來就像無意義的字符排列,不太好看也不符合我們一般的網址瀏覽習慣。不配置時是這樣的:[http://localhost:8080/#/users](https://link.jianshu.com?t=http%3A%2F%2Flocalhost%3A8080%2F%23%2Fusers),多個#號。
### 十二、路由組件傳參
(這點是直接粘貼的vue官網上的教程,此處是重點要多看多體會!)
在組件中使用 $route 會使之與其對應路由形成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性。
**解耦前:**
`id`不能直接拿出來使用
~~~dart
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
~~~
**使用 props 將組件和路由解耦:**
~~~csharp
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true },
// 對于包含命名視圖的路由,你必須分別為每個命名視圖添加 `props` 選項:
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
})
~~~
這樣你便可以在任何地方使用該組件,使得該組件更易于重用和測試。
**1.布爾模式**
如果 props 被設置為 true,route.params 將會被設置為組件屬性。
**2.對象模式**
如果 props 是一個對象,它會被按原樣設置為組件屬性。當 props 是靜態的時候有用。
~~~csharp
const router = new VueRouter({
routes: [
{ path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
]
})
~~~
**3.函數模式**
你可以創建一個函數返回 props。這樣你便可以將參數轉換成另一種類型,將靜態值與基于路由的值結合等等。
~~~jsx
const router = new VueRouter({
routes: [
{ path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
]
})
~~~
`/search?q=vue`會將`{query: 'vue'}`作為屬性傳遞給 SearchUser 組件。
請盡可能保持 props 函數為無狀態的,因為它只會在路由發生變化時起作用。如果你需要狀態來定義 props,請使用包裝組件,這樣 Vue 才可以對狀態變化做出反應。
~~~jsx
function dynamicPropsFn (route) {
const now = new Date()
return {
name: (now.getFullYear() + parseInt(route.params.years)) + '!'
}
}
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [
{ path: '/', component: Hello }, // No props, no nothing
{ path: '/hello/:name', component: Hello, props: true }, // Pass route.params to props
{ path: '/static', component: Hello, props: { name: 'world' }}, // static values
{ path: '/dynamic/:years', component: Hello, props: dynamicPropsFn }, // custom logic for mapping between route and props
{ path: '/attrs', component: Hello, props: { name: 'attrs' }}
]
})
~~~
187人點贊
[技術文檔](/nb/22744967)
作者:東西里
鏈接:[https://www.jianshu.com/p/514c7588e877](https://www.jianshu.com/p/514c7588e877)
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
- PHP新特性
- 一些常識
- PHP常見header頭
- Nginx配置文件
- 常用工具類
- PHP實現的一個時間幫助類
- PHP原生生成EXCEL
- PHP地理位置計算
- PHP獲取服務器狀態
- 駝峰轉下劃線
- 百度地圖兩點坐標距離計算
- 判斷是否是url
- 郵件發送類
- 阿拉伯數字轉化為大寫
- 獲取漢字首個拼音
- 根據身份證號獲取星座
- 生成驗證碼類
- 生成唯一ID
- 身份證驗證類
- PHP中文轉拼音
- curl獲取網頁內容
- 快遞查詢api
- 快遞API類
- 上傳圖片類
- 股票類
- 找回密碼類
- 校驗數據規則
- PHP獲取收集相關信息
- 字符串截取助手函數
- 網頁中提取關鍵字
- 檢測瀏覽器語言
- PHP實現微信紅包拆分算法
- 常用函數
- 微信相關
- 網絡知識
- LX1 Laravel / PHP 擴展包視頻教程
- THINKPHP5學習
- 高級查詢
- Vue學習
- Vue全家桶
- Vue-CLI 3.x 自動部署項目至服務器
- Vue2全家桶
- Vue2全家桶之一:vue-cli(vue腳手架)超詳細教程
- Vue2全家桶之二:vue-router(路由)詳細教程,看這個就夠了
- Vue2全家桶之三:vue-resource(不推薦)----axios(推薦)
- 前端相關
- sublime text3 配置less編譯環境
- 服務器搭建相關
- supervisor
- Supervisor 安裝與配置 Linux進程管理
- supervisor 永不掛掉的進程 安裝以及使用
- Supervisor進程管理&開機自啟
- php實現定時任務
- 使用sublime text3 連接sftp/ftp(遠程服務器)
- Redis相關
- linux服務器重啟后導致redis數據丟失
- 搜索引擎SEO
- 百度收錄權威鏈接,指向真正需要收錄的地址rel
- 軟件相關
- sublime
- sublime Text3修改側邊欄的主題
- sublime和vscode比較
- Acrylic DNS Proxy 使用方法
- 技術類網址收藏