若是你用vue-cli腳手架來搭建項目,配置過程會選擇是否用到路由(詳細見我上一篇簡書),若是選擇y,後面下載依賴會自動下載vue-router。
這裏仍是說一下安裝:npm install vue-router
javascript
若是在一個模塊化工程中使用它,必需要經過 Vue.use() 明確地安裝路由功能,用vue-cli生產了咱們的項目結構,src文件目錄下會有一個router文件夾,此處就是編寫路由組件的地方。在src/router/index.js,這個文件就是路由的核心文件:css
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}, ] } ] })
1.router-link 是一個組件,它默認會被渲染成一個帶有連接的a標籤,經過to屬性指定連接地址。
注意:被選中的router-link將自動添加一個class屬性值.router-link-active。html
<router-link to="/">[text]</router-link>
2.router-view 用於渲染匹配到的組件。
①.能夠給router-view組件設置transition過渡(Vue2.0 Transition常見用法全解惑)。vue
<transition name="fade"> <router-view ></router-view> </transition>
css過渡類名:
組件過渡過程當中,會有四個CSS類名進行切換,這四個類名與transition的name屬性有關,好比name="fade",會有以下四個CSS類名:java
從上面四個類名能夠看出,fade-enter-active和fade-leave-active在整個進入或離開過程當中都有效,因此CSS的transition屬性在這兩個類下進行設置。react
過渡模式mode:正則表達式
②.還能夠配合<keep-alive>
使用,keep-alive能夠緩存數據,這樣不至於從新渲染路由組件的時候,以前那個路由組件的數據被清除了。好比對當前的路由組件a進行了一些DOM操做以後,點擊進入另外一個路由組件b,再回到路由組件a的時候以前的DOM操做還保存在,若是不加keep-alive再回到路由組件a時,以前的DOM操做就沒有了,得從新進行。若是你的應用裏有一個購物車組件,就須要用到keep-alive。vue-router
<transition> <keep-alive> <router-view></router-view> </keep-alive> </transition>
咱們常常須要把某種模式匹配到的全部路由,全都映射到同個組件。
調用router的map方法映射路由,每條路由以key-value的形式存在,key是路徑,value是組件。例如:'/home'是一條路由的key,它表示路徑;{component: Home}則表示該條路由映射的組件:vue-cli
router.map({
'/home': { component: Home }, '/about': { component: About } })
例如,咱們有一個 User 組件,對於全部 ID 各不相同的用戶,都要使用這個組件來渲染。那麼,咱們能夠在 vue-router 的路由路徑中使用『動態路徑參數』來達到這個效果。npm
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 中。例如:
<router-link :to="{name:‘dxl’,params:{key:value}}">東西里</router-link>
$route.params.username
進行接收.上面第五點也有提到。 :冒號的形式傳遞參數
(1).在router路由配置文件裏以冒號的形式設置參數
{ path:'/params/:newsId/:userName, component:Params }
(2).組件形式,在src/components目錄下創建咱們params.vue組件。
咱們在頁面裏輸出了url傳遞的參數。
<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).<router-view>標籤path路徑中傳值
<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 對象:
const User = { template: '...', watch: { '$route' (to, from) { // 對路由變化做出響應... } } }
(2).beforeRouteUpdate 導航守衛
若是目的地和當前路由相同,只有參數發生了改變 (好比從一個用戶資料到另外一個 /users/1
-> /users/2
),你須要使用 beforeRouteUpdate
來響應這個變化 (好比抓取用戶信息)。
const User = { template: '...', beforeRouteUpdate (to, from, next) { // react to route changes... // don't forget to call next() } }
// 定義路由的時候以下定義,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基本重定向:
const routes = [ { path: '/', redirect: '/goods'} ] 重定向的目標也能夠是一個命名的路由。 const routes = [ { path: '/', redirect: { name: 'goods' }} ] 重定向時也能夠傳遞參數 { path:'/', redirect:'/goods/:newsId(\\d+)/:userName' }
★.這裏不得不提到alias別名的使用。
1.首先咱們在路由配置文件裏給路徑起一個別名,dxl。
{
path: '/hi', component: Hi, alias:'/dxl' }
2.配置咱們的<router-link>,起過別名以後,能夠直接使用<router-link>標籤裏的to屬性,進行從新定向。
<router-link to="/dxl">jspang</router-link>
區別:
★★★.注意一個大坑:
別名alias在path爲'/'中,是不起做用的。
{
path: '/', component: Hello, alias:'/home' }
1.router.push( )
想要導航到不一樣的 URL,則使用 router.push (在建立vue實例並掛載後調用)。router.push方法就是用來動態導航到不一樣的連接的,這個方法會向 history 棧添加一個新的記錄,因此,當用戶點擊瀏覽器後退按鈕時,則回到以前的 URL。
當你點擊 <router-link> 時,這個方法會在內部調用,因此說,點擊 <router-link :to="..."> 等同於調用 router.push(...)。
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 記錄。
// 在瀏覽器記錄中前進一步,等同於 history.forward() router.go(1) // 後退一步記錄,等同於 history.back() router.go(-1)
自定義一個goback()方法,並使用this.$router.go(-1),進行後退操做
<script> export default { name: 'app', methods:{ goback(){ this.$router.go(-1); }, goHome(){ this.$router.push('/'); } } } </script>
1.路由配置文件中的鉤子函數:
在路由文件中咱們只能寫一個beforeEnter,就是在進入此路由配置時:
{
path:'/params/:newsId(\\d+)/:userName', component:Params, beforeEnter:(to,from,next)=>{ console.log('我進入了params模板'); console.log(to); console.log(from); next(); },
三個參數:
2.寫在模板中的鉤子函數:
寫在模板中就能夠有兩個鉤子函數可使用。
beforeRouteEnter:在路由進入前的鉤子函數。
beforeRouteLeave:在路由離開前的鉤子函數。
export default { name: 'params', data () { return { msg: 'params page' } }, beforeRouteEnter:(to,from,next)=>{ console.log("準備進入路由模板"); next(); }, beforeRouteLeave: (to, from, next) => { console.log("準備離開路由模板"); next(); } }
★此處經常使用於數據獲取。
$route.params.id
獲取文章數據:<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 } }) } } }
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 } } } }
vue-router 默認 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,因而當 URL 改變時,頁面不會從新加載。
若是不想要很醜的 hash,咱們能夠用路由的 history 模式,這種模式充分利用 history.pushState API 來完成 URL 跳轉而無須從新加載頁面。
const router = new VueRouter({ mode: 'history', routes: [...] })
在學習過渡效果的時候,咱們學了mode的設置,可是在路由的屬性中還有一個mode。
mode的兩個值:
const router = new VueRouter({ mode: 'history', routes: [ { path: '*', component: Error} ] })
這裏的path:'*'就是找不到頁面時的配置,component是咱們新建的一個Error.vue的文件
(這點是直接粘貼的vue官網上的教程,此處是重點要多看多體會!)
在組件中使用 $route 會使之與其對應路由造成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性。
解耦前:
id
不能直接拿出來使用
const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] })
使用 props 將組件和路由解耦:
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 是靜態的時候有用。
const router = new VueRouter({ routes: [ { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } } ] })
3.函數模式
你能夠建立一個函數返回 props。這樣你即可以將參數轉換成另外一種類型,將靜態值與基於路由的值結合等等。
const router = new VueRouter({ routes: [ { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) } ] })
/search?q=vue
會將{query: 'vue'}
做爲屬性傳遞給 SearchUser 組件。
請儘量保持 props 函數爲無狀態的,由於它只會在路由發生變化時起做用。若是你須要狀態來定義 props,請使用包裝組件,這樣 Vue 才能夠對狀態變化作出反應。
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' }} ] })