Vue路由vue-router

概述

前端路由
路由就是根據(jù)不同的url地址來展示不同的內(nèi)容或頁面.
Vue Router 是 Vue.js 官方的路由管理器
github: https://github.com/vuejs/vue-router
中文官方網(wǎng)站https://router.vuejs.org/zh/
中文API文檔 https://router.vuejs.org/zh/api/

vue-router安裝與結(jié)構(gòu)

npm isntall vue-router --save

vue-router是Vue的一個插件闲勺,需要在Vue的全局應(yīng)用中通過Vue.use()將他納入到Vue實例中
創(chuàng)建項目 router-demo 選擇Manually select features

$vue create router-demo

Vue CLI v3.9.2
? Please pick a preset: Manually select features
? Check the features needed for your project:
 ? Babel
 ? TypeScript
 ? Progressive Web App (PWA) Support
?? Router
 ? Vuex
 ? CSS Pre-processors
 ? Linter / Formatter
 ? Unit Testing
 ? E2E Testing

會在當(dāng)前項目src目錄下自動創(chuàng)建router.js文件

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    }
  ]
})

一條路由的實現(xiàn)需要三部分:
name 名稱
path, 路徑
component 組件
啟動路由器
在main.js 入口文件中啟動路由器

Helloworld

接著使用上面的

  1. 創(chuàng)建組件Bar.vue
<template>
    <div >
        <h1>Bar</h1>
        <router-link to="foo">跳轉(zhuǎn)到Foo</router-link>
    </div>
</template>

<script>
    export default {
        name: 'Bar',
    }
</script>

  1. 創(chuàng)建組件Foo.vue
<template>
    <div>
        <h1>Foo</h1>
        <router-link to="bar">跳轉(zhuǎn)到Bar</router-link>
    </div>
</template>

<script>
    export default {
        name: "Foo",
    }
</script>

<style scoped>

</style>
  1. 創(chuàng)建文件router,在其目錄下創(chuàng)建index.js文件
import Router from 'vue-router'
import Vue from 'vue'
Vue.use(Router)

import Bar from '../components/Bar'
import Foo from '../components/Foo'

export default new Router({
    routes: [
        {
          path:"/",
          redirect:"/foo"
        },
        {
            path: '/foo',
            component: Foo
        },
        {
            path: '/bar',
            component: Bar
        }
    ]
});

  1. 將App.vue修改
<template>
    <div id="app">
        <img alt="Vue logo" src="./assets/logo.png">
        <router-view></router-view>
        </div>
</template>

<style>
    #app {
        text-align: center;
        margin-top: 60px;
    }
</style>
  1. 在main.js注冊路由器
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'

Vue.config.productionTip = false;

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

動態(tài)路由

創(chuàng)建組件User.vue

<template>
    <div>
        {{$route.params.id}}
    </div>
</template>

修改router目錄的index文件

import Router from 'vue-router'
import Vue from 'vue'
Vue.use(Router)
import User from  '../components/User'

export default new Router({
    routes: [
        {
            path:'/user/:id',
            component:User
        }
    ]
});

訪問的http://localhost:8080/#/user/12347

圖片.png

設(shè)置“路徑參數(shù)”,將User.vue 修改成

<template>
    <div>
        {{$route.query.id}}
    </div>
</template>

增加路由配置

        {
            path:'/user',
            component:User
        }

訪問路徑 http://localhost:8080/#/user?id=2

嵌套路由router-view

創(chuàng)建組件文件Profile.vue

<template>
    <div>
        用戶畫子界面
    </div>
</template>

<script>
    export default {
        name: "Profile"
    }
</script>

<style scoped>

</style>

修改路由文件router/index.js

import Router from 'vue-router'
import Vue from 'vue'
Vue.use(Router)
import User from  '../components/User'
import Profile from '../components/Profile'
export default new Router({
    routes: [

        {
            path:'/user',
            component:User,
            children:[
                {
                    path:"profile",
                    component:Profile
                }

            ]
        },
        {
            path:'/user/:id',
            component:User
        }

    ]
});

同一個路徑可以匹配多個路由,此時睹栖,匹配的優(yōu)先級就按照路由的定義順序:誰先定義的赃额,誰的優(yōu)先級就最高伸辟。
訪問http://localhost:8080/#/user/profile

圖片.png

路由組件傳參

方式 1: 路由路徑攜帶參數(shù)(param/query)
配置路由

children: [
{
path: 'mdetail/:id',
component: MessageDetail
}
]

路由路徑
參數(shù)傳遞 注意需要加上冒號:

<router-link :to="'/home/message/mdetail/'+m.id">{{m.title}}</router-link>

路由組件中讀取請求參數(shù),獲取傳遞數(shù)據(jù) 注意是route 而不是router

this.$route.params.id

方式2 <router-view>屬性攜帶數(shù)據(jù)

<router-view :msg="msg"></router-view>

緩存路由組件對象

  1. 默認(rèn)情況下, 被切換的路由組件對象會死亡釋放, 再次回來時是重新創(chuàng)建的
  2. 如果可以緩存路由組件對象, 可以提高用戶體驗
<keep-alive>
<router-view></router-view>
</keep-alive>

路由導(dǎo)航

相關(guān) API

  1. this.$router.push(path): 相當(dāng)于點擊路由鏈接(可以返回到當(dāng)前路由界面)
// 字符串
router.push('home')
// 對象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 帶查詢參數(shù),變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 path,params 會被忽略稻扬,上述例子中的 query 并不屬于這種情況攒巍。取而代之的是下面例子的做法嗽仪,你需要提供路由的 name 或手寫完整的帶有參數(shù)的 path:

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
  1. this.$router.replace(path): 用新路由替換當(dāng)前路由(不可以返回到當(dāng)前路由界面)
  2. this.$router.back(): 請求(返回)上一個記錄路由
  3. this.$router.go(-1): 請求(返回)上一個記錄路由
  4. this.$router.go(1): 請求下一個記錄路由

路由元數(shù)據(jù)

定義路由的時候可以配置 meta 字段:

import Router from 'vue-router'
import Vue from 'vue'
Vue.use(Router)
import User from  '../components/User'
import Profile from '../components/Profile'

const router = new Router({
    routes: [
        {
            path:'/user',
            component:User,
            children:[
                {
                    path:"profile",
                    component:Profile
                }
            ]
        },
        {
            path:'/user/:id',
            component:User,
            meta:{
                requireAuth:true
            }
        }

    ]
});

router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requireAuth)) {
        next()
    }
})

export default router

路由組件傳參

使用route的props進(jìn)行解耦.提高組件的復(fù)用,同時不改變url

修改user.vue組件文件如下

<template>
    <div>
        <p>姓名:{{this.name}}</p>
    </div>
</template>

<script>
    export default {
        name: "User",
        props:["name"]
    }
</script>

<style scoped>

</style>

修改路由文件router/index.js 文件如下

import Router from 'vue-router'
import Vue from 'vue'
Vue.use(Router)
import User from  '../components/User'

const router = new Router({
    routes: [
        {
            path:"/user/profile",
            component:User,
            props:{name:"tony"}
        },
        {
            path:"/user/search",
            component:User,
            props: (route)=>({name:route.query.name})
        },
        {
            path:"/user/:name",
            component:User,
            props:true
        },
    ]
});

function searchName(route){
    return {name:(route.query.name)}
}

export default router

函數(shù)返回的是對象類型的 ,props: (route)=>({name:route.query.name}) 等價于

function searchName(route){
    return {name:(route.query.name)}
}

訪問接口http://localhost:8081/#/user/search?name=tony
訪問接口http://localhost:8081/#/user/profile
訪問接口http://localhost:8081/#/user/tony

圖片.png

路由懶加載

當(dāng)打包構(gòu)建應(yīng)用時柒莉,JavaScript 包會變得非常大闻坚,影響頁面加載。如果我們能把不同路由對應(yīng)的組件分割成不同的代碼塊兢孝,然后當(dāng)路由被訪問的時候才加載對應(yīng)組件窿凤,這樣就更加高效了。
結(jié)合 Vue 的異步組件和 Webpack 的代碼分割功能跨蟹,輕松實現(xiàn)路由組件的懶加載雳殊。
首先,可以將異步組件定義為返回一個 Promise 的工廠函數(shù) (該函數(shù)返回的 Promise 應(yīng)該 resolve 組件本身):

const Foo = () => Promise.resolve({ /* 組件定義對象 */ })

第二窗轩,在 Webpack 2 中夯秃,我們可以使用動態(tài) import

語法來定義代碼分塊點 (split point):

import('./Foo.vue') // 返回 Promise

注意
如果您使用的是 Babel,你將需要添加 syntax-dynamic-import

插件痢艺,才能使 Babel 可以正確地解析語法仓洼。
結(jié)合這兩者,這就是如何定義一個能夠被 Webpack 自動代碼分割的異步組件堤舒。

const Foo = () => import('./Foo.vue')

在路由配置中什么都不需要改變色建,只需要像往常一樣使用 Foo

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

把組件按組分塊

有時候我們想把某個路由下的所有組件都打包在同個異步塊 (chunk) 中。只需要使用 命名 chunk

植酥,一個特殊的注釋語法來提供 chunk name (需要 Webpack > 2.4)镀岛。

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

Webpack 會將任何一個異步模塊與相同的塊名稱組合到相同的異步塊中弦牡。

組件渲染

在index.html處有個id="app"的div,在App.vue中也有一個id="app"的div漂羊。頁面渲染的就是這個組件驾锰。


圖片.png

在這個App.vue中有個router-view標(biāo)簽,默認(rèn)在這渲染當(dāng)路由為"/"指向的組件走越,路由設(shè)置在src/router/index.js中

圖片.png

這樣就可以使用HelloWorld組件了椭豫。

圖片.png

這張圖可以更清楚得讓大家明白router-view標(biāo)簽的作用


圖片.png

*注意,當(dāng)有多個組件的時候旨指,就不是component屬性而是components赏酥,記得注冊的組件上面都要用import導(dǎo)入

當(dāng)組件里有自己的子組件的情況下,就需要使用到router-link標(biāo)簽了谆构,它其實是一個a標(biāo)簽


圖片.png

那么router-view和router-link的區(qū)別是什么呢裸扶?

目前來說,router-link和router-view結(jié)合使用搬素,可以在組件中通過點擊渲染子組件呵晨;
單獨使用router-view就可以在當(dāng)前組件中重根據(jù)name屬性選擇渲染組件;
單獨使用router-link就可以整個切換到to屬性指定路由的組件熬尺;

最后摸屠,這個單頁面開發(fā)的意思就是,這個項目只有index.html這個頁面粱哼,我們通過使用不同的組件像拼裝機器人一樣獲得不同的頁面展示季二,而src下的App.vue就是所有組件的父組件,所有其它組件都通過路由渲染到它里面的router-view中揭措,然后再將App.vue渲染到index.html中胯舷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蜂筹,隨后出現(xiàn)的幾起案子需纳,更是在濱河造成了極大的恐慌芦倒,老刑警劉巖艺挪,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異兵扬,居然都是意外死亡麻裳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門器钟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來津坑,“玉大人,你說我怎么就攤上這事傲霸〗澹” “怎么了眉反?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長穆役。 經(jīng)常有香客問我寸五,道長,這世上最難降的妖魔是什么耿币? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任梳杏,我火速辦了婚禮,結(jié)果婚禮上淹接,老公的妹妹穿的比我還像新娘十性。我一直安慰自己,他們只是感情好塑悼,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布劲适。 她就那樣靜靜地躺著,像睡著了一般厢蒜。 火紅的嫁衣襯著肌膚如雪减响。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天郭怪,我揣著相機與錄音支示,去河邊找鬼。 笑死鄙才,一個胖子當(dāng)著我的面吹牛颂鸿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播攒庵,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼嘴纺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了浓冒?” 一聲冷哼從身側(cè)響起栽渴,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎稳懒,沒想到半個月后闲擦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡场梆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年墅冷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片或油。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡寞忿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出顶岸,到底是詐尸還是另有隱情腔彰,我是刑警寧澤叫编,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站霹抛,受9級特大地震影響宵溅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜上炎,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一恃逻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧藕施,春花似錦寇损、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诲祸,卻和暖如春浊吏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背救氯。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工找田, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人着憨。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓墩衙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甲抖。 傳聞我的和親對象是個殘疾皇子漆改,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容