溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

vue獲取參數(shù)的方式有哪些

發(fā)布時(shí)間:2022-08-15 16:16:14 來(lái)源:億速云 閱讀:171 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“vue獲取參數(shù)的方式有哪些”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“vue獲取參數(shù)的方式有哪些”吧!

    路由基礎(chǔ)

    1.SPA與路由

    1.1 SPA介紹

    1.1.1 什么是SPA?

    SPA(single-page application),只有一個(gè)HTML頁(yè)面,通過(guò)路由實(shí)現(xiàn)頁(yè)面內(nèi)的局部切換,公共資源部分只加載一次。

    vue獲取參數(shù)的方式有哪些

    我們熟知的JS框架如react,vue,angular,ember都屬于SPA。

    1.1.2 什么是MPA(多頁(yè)面應(yīng)用)

    平常寫(xiě)的普通頁(yè)面就是MPA,通過(guò)a標(biāo)簽實(shí)現(xiàn)頁(yè)面切換,每次切換頁(yè)面都要重新加載公共資源部分。

    1.1.3 SPA和MPA的區(qū)別

    區(qū)別SPAMPA
    組成一個(gè)外殼頁(yè)面和多個(gè)頁(yè)面片段組成多個(gè)完整的頁(yè)面組成
    公用資源(js,css,img)公用,只加載一次每個(gè)頁(yè)面都需要加載
    刷新方式局部刷新整體刷新
    URL模式哈希模式(a.com/#/page1)/歷史模式(a.com/page1)歷史模式
    用戶體驗(yàn)用戶體驗(yàn)好,頁(yè)面切換快用戶體驗(yàn)不好,頁(yè)面切換慢
    轉(zhuǎn)場(chǎng)動(dòng)畫(huà)容易實(shí)現(xiàn)無(wú)法實(shí)現(xiàn)
    數(shù)據(jù)傳遞容易依賴URL或本地存儲(chǔ)
    SEO實(shí)現(xiàn)比較困難簡(jiǎn)單
    開(kāi)發(fā)成本難度高,需要借助專業(yè)的框架難度低,但是重復(fù)代碼比較多
    維護(hù)成本相對(duì)比較低相對(duì)比較高

    1.1.4 SPA的優(yōu)缺點(diǎn)

    優(yōu)點(diǎn):

    • 1,用戶體驗(yàn)好,快,內(nèi)容的改變不需要重新加載整個(gè)頁(yè)面,基于這一點(diǎn)spa對(duì)服務(wù)器壓力較小

    • 2,前后端分離

    • 3,頁(yè)面效果會(huì)比較炫酷(比如切換頁(yè)面內(nèi)容時(shí)的專場(chǎng)動(dòng)畫(huà))

    缺點(diǎn):

    • 1,不利于seo(搜索引擎優(yōu)化(Search Engine Optimization,SEO)是一種通過(guò)了解搜索引擎的運(yùn)行規(guī)則來(lái)調(diào)整網(wǎng)站,以提高目標(biāo)網(wǎng)站在有關(guān)搜索引擎內(nèi)排名的方式);

    • 2,導(dǎo)航不可用,如果一定要導(dǎo)航需要自行實(shí)現(xiàn)前進(jìn)、后退。(由于是單頁(yè)面不能用瀏覽器的前進(jìn)后退功能,所以需要自己建立堆棧管理)

    • 3,不支持低版本的瀏覽器,最低只支持到IE9

    • 4,初次加載時(shí)耗時(shí)多

    • 5,頁(yè)面復(fù)雜度提高很多

    1.2 路由介紹

    簡(jiǎn)單舉例說(shuō)明,假如我們有一臺(tái)提供 Web 服務(wù)的服務(wù)器的網(wǎng)絡(luò)地址是:10.0.0.1,而該 Web 服務(wù)又提供了三個(gè)可供用戶訪問(wèn)的頁(yè)面,其頁(yè)面 URI 分別是:

    http://10.0.0.1/
    http://10.0.0.1/about
    http://10.0.0.1/concat

    那么其路徑就分別是 /,/about,/concat。

    當(dāng)用戶使用 http://10.0.0.1/about 來(lái)訪問(wèn)該頁(yè)面時(shí),Web 服務(wù)會(huì)接收到這個(gè)請(qǐng)求,然后會(huì)解析 URL 中的路徑 /about,在 Web 服務(wù)的程序中,該路徑對(duì)應(yīng)著相應(yīng)的處理邏輯,程序會(huì)把請(qǐng)求交給路徑所對(duì)應(yīng)的處理邏輯,這樣就完成了一次「路由分發(fā)」,這個(gè)分發(fā)就是通過(guò)「路由」來(lái)完成的。

    簡(jiǎn)單的說(shuō),路由是根據(jù)不同的 url 地址展示不同的內(nèi)容或頁(yè)面。

    1.3前端路由原理

    路由的概念在軟件工程中出現(xiàn),最早是在后端路由中實(shí)現(xiàn)的。服務(wù)器直接生產(chǎn)渲染好對(duì)應(yīng)的HTML頁(yè)面, 返回給客戶端進(jìn)行展示。

    前端路由是如何做到URL和內(nèi)容進(jìn)行映射呢?監(jiān)聽(tīng)URL的改變。

    1.3.1 URL的hash

    URL的hash也就是錨點(diǎn)(#), 本質(zhì)上是改變window.location的href屬性;我們可以通過(guò)直接賦值location.hash來(lái)改變href, 但是頁(yè)面不發(fā)生刷新;另外每次 hash 值的變化,還會(huì)觸發(fā)hashchange 這個(gè)事件,通過(guò)這個(gè)事件我們就可以知道 hash 值發(fā)生了哪些變化。然后我們便可以監(jiān)聽(tīng)hashchange來(lái)實(shí)現(xiàn)更新頁(yè)面部分內(nèi)容的操作。

    <div id="app">
        <a href="#/home" rel="external nofollow" >home</a>
        <a href="#/about" rel="external nofollow" >about</a>
        <div id="router-view"></div>
    </div>
    <script>
        const routerView = document.querySelector('#router-view');
        // url的hash
        // URL的hash也就是錨點(diǎn),本質(zhì)上就是改變window.location 的 href 屬性
        // 我們可以通過(guò)直接賦值location.hash 來(lái)改變 href 但是頁(yè)面不會(huì)刷新
        window.addEventListener('hashchange',()=>{
            console.log(location.hash);
            if(location.hash==="#/home"){
                routerView.innerHTML = "home";
            }else if(location.hash==="#/about"){
                routerView.innerHTML = "about";
            }
        })
    </script>

    hash的優(yōu)勢(shì)就是兼容性更好,在老版IE中都可以運(yùn)行,但是缺陷是有一個(gè)#,顯得不像一個(gè)真實(shí)的路徑。

    1.3.2 HTML5的History

    14年后,因?yàn)镠TML5標(biāo)準(zhǔn)發(fā)布。多了兩個(gè) API,pushState 和 replaceState,通過(guò)這兩個(gè) API 可以改變 url 地址且不會(huì)發(fā)送請(qǐng)求。

    通過(guò)這些就能用另一種方式來(lái)實(shí)現(xiàn)前端路由了,但原理都是跟 hash 實(shí)現(xiàn)相同的。用了 HTML5 的實(shí)現(xiàn),單頁(yè)路由的 url 就不會(huì)多出一個(gè)#,變得更加美觀。但因?yàn)闆](méi)有 # 號(hào),所以當(dāng)用戶刷新頁(yè)面之類的操作時(shí),瀏覽器還是會(huì)給服務(wù)器發(fā)送請(qǐng)求。

    為了避免出現(xiàn)這種情況,所以這個(gè)實(shí)現(xiàn)需要服務(wù)器的支持,需要把所有路由都重定向到根頁(yè)面;

    <div class="nav">
        <a onclick="linkTo(1)">link1</a>
        <a onclick="linkTo(2)">link2</a>
    </div>
    <div id="router-view">
    </div>
    <script>
        var view = document.getElementById('router-view');
        function linkTo(link){
            switch(link) {
                case 1: {
                    window.history.pushState({a:1}, 'mylink1', '/link1');
                    view.innerHTML = 'link1 content';
                    break;
                }
                case 2: {
                    window.history.pushState({a:1}, 'mylink2', '/link2');
                    view.innerHTML = 'link2 conetnt';
                    break;
                }
                default: 
                    return;
            }
            return false;
        }
    </script>

    2.vue-router基礎(chǔ)用法

    通過(guò)vue的路由可實(shí)現(xiàn)多視圖的單頁(yè)面Web應(yīng)用。VueRouter文檔

    我們之前使用過(guò)is特性來(lái)實(shí)現(xiàn)動(dòng)態(tài)組件,vue-router的實(shí)現(xiàn)原理與之類似。vue-router展示不同的頁(yè)面事實(shí)上就是動(dòng)態(tài)加載不同的組件。

    當(dāng)我們的地址欄發(fā)生了變化,vue-router就會(huì)監(jiān)聽(tīng)到。根據(jù)它里面配置的匹配規(guī)則,展示不同的組件。

    2.1 下載VueRouter

    2.1.1 直接下載

    VueRouter下載地址 : https://unpkg.com/vue-router/dist/vue-router.js

    2.1.2 使用CDN地址

    <script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js"></script>

    2.1.3 腳手架

    在使用腳手架搭建項(xiàng)目時(shí),選擇 Vue-router,項(xiàng)目創(chuàng)建好之后默認(rèn)安裝vue-router。如果創(chuàng)建項(xiàng)目時(shí),沒(méi)有選擇,也可以使用模塊化開(kāi)發(fā)的方式。執(zhí)行如下的命令來(lái)安裝Vue Router。

    npm i vue-router

    2.2 一般使用過(guò)程

    2.2.1 使用router-link組件來(lái)定義導(dǎo)航

    在app.vue的template中修改成如下代碼

    <template>
        <div>
            <!-- router-link相應(yīng)于a標(biāo)簽,to相當(dāng)于href,指要單擊跳轉(zhuǎn)到顯示那個(gè)組件的內(nèi)容 ,最終瀏覽器還是會(huì)把router-link解析為a標(biāo)簽-->
            <router-link to="/about">關(guān)于我們</router-link>
            <router-link to="/news">新聞</router-link>
        </div>
    </template>

    2.2.2 指定組件的渲染位置

    通過(guò)router-view組件指定組件的渲染位置。

    <template>
        <!-- ... -->
        <div class="container">
            <!-- router-view指定顯示路由導(dǎo)航內(nèi)容的位置,也就是單擊【關(guān)于我們】或【新聞】連接的內(nèi)容都在router-view組件指定位置顯示 -->
            <router-view></router-view>
        </div>
    </template>

    當(dāng)單擊鏈接router-link的時(shí)候,會(huì)在router-view所在的位置渲染組件的模板內(nèi)容??梢园裷outer-view理解為占位符。

    再準(zhǔn)備好樣式

    <style>
        .container {
            background-color:blanchedalmond;
            margin-top: 10px;
            width: 600px;
            height: 300px;
        }
    </style>

    2.2.3 定義路由組件

    也就是每個(gè)鏈接顯示的內(nèi)容,這里只是演示前端路由的基本用法,所以組件定義很簡(jiǎn)單。新建兩個(gè)文件 About.vue和News.vue

    <template>
    	<h4>關(guān)于我們</h4>
    </template>
    <template>
    	<h4>最熱新聞</h4>
    </template>

    2.2.4 定義路由,創(chuàng)建路由實(shí)例

    src目錄下新建一個(gè)router文件夾,如果創(chuàng)建項(xiàng)目時(shí),已經(jīng)選擇了Vue-router則會(huì)自動(dòng)創(chuàng)建。創(chuàng)建index.js文件,代碼如下:

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import Films from '@/components/About'
    import Cinemas from '@/components/News'
    // 注冊(cè)路由插件, 兩個(gè)全局 router-view router-link
    Vue.use(VueRouter) 
    // 配置表,有多條路由時(shí),通常定義為一個(gè)常量數(shù)組,里面每個(gè)對(duì)象就是一個(gè)路由
    const routes = [
        // 定義路由格式:path指定路由的url,component指定當(dāng)單擊path指定的url時(shí)顯示哪個(gè)組件內(nèi)容。
        { path: '/about', component: About },
        { path: '/news', component: News }
    ]
    //能new VueRouter就是因?yàn)橐肓藇ue-router.js。
    export default new VueRouter({
        // routes:routes//左邊routes為要設(shè)置的路由選項(xiàng)routes,右邊routes為選項(xiàng)值,名字當(dāng)然可以不同,但是一般設(shè)置為相同。第2步不單獨(dú)定義,直接寫(xiě)在routes里也可以
        routes,
        mode:'history',
        linkActiveClass:'active'
    });

    2.2.5 掛載路由實(shí)例對(duì)象

    在main的js中,掛在路由實(shí)例對(duì)象.

    import router from './router'
    //創(chuàng)建vue根實(shí)例,并將上面的路由實(shí)例掛載到vue實(shí)例上,也稱為注入路由,就是告訴vue實(shí)例有這么一個(gè)路由了。
    //怎么告訴呢?通過(guò)router選項(xiàng)
    var vm = new Vue({
        el: "#app",
        // router:router//同樣:左右兩邊名稱相同,可以簡(jiǎn)寫(xiě)
        router//注入路由
    })

    2.3 修改路由模式

    上面的案例中,當(dāng)我們切換路由時(shí)發(fā)現(xiàn)地址欄后面會(huì)自動(dòng)再加一個(gè)“#”。為什么是這種顯示模式呢?因?yàn)樵谑褂肰ue Router創(chuàng)建路由實(shí)例時(shí),默認(rèn)采用的是hash路由配置模式。這種模式的優(yōu)點(diǎn)是各種瀏覽器的兼容性比較好。

    但是hash模式下url需要帶“#”符號(hào),不僅看起來(lái)不舒服,而且有些場(chǎng)景下是會(huì)破壞路由中的"#"(微信分享頁(yè)面就會(huì)把"#"后邊的內(nèi)容處理掉),所以我們可以將路由實(shí)例修改為history路由模式。只需要在創(chuàng)建路由實(shí)例時(shí),設(shè)置mode選項(xiàng)為history即可。 

    const router = new VueRouter({
        routes,
        mode:'history'
    })

    這種history路由模式的缺點(diǎn)是URL兼容性不好,并且懼怕刷新。

    2.4 為當(dāng)前導(dǎo)航添加樣式

    觀察生成的HTML代碼,會(huì)發(fā)現(xiàn)在當(dāng)前導(dǎo)航中多了兩個(gè)class類名。

    <a class="router-link-exact-active rotuer-link-active">關(guān)于我們</a>

    但是此類名并沒(méi)有設(shè)置樣式,需要自己手動(dòng)設(shè)置具體樣式。

    .rotuer-link-active{
        font-size:20px;
        color:red;
        text-decoration: none;
    }

    需要注意的是,樣式名取最后一個(gè)即可,這兩者的區(qū)別在后面學(xué)習(xí)嵌套路由時(shí)再說(shuō)明。

    另外,如果覺(jué)得系統(tǒng)默認(rèn)樣式名太長(zhǎng),不好記憶可以進(jìn)行修改。

    在創(chuàng)建路由實(shí)例時(shí),可通過(guò)linkActiveClass選項(xiàng),設(shè)置樣式名。

    const router = new VueRouter({
        routes,
        mode:'history',
        linkActiveClass:'active'
    })

    2.5 路由重定向

    還有一個(gè)問(wèn)題,不論哪種路由模式,剛打開(kāi)頁(yè)面既沒(méi)有顯示【關(guān)于我們】的內(nèi)容,也沒(méi)顯示【新聞】鏈接的內(nèi)容。我們可以在配置路由時(shí),在增加一個(gè)路由,作用是:找不到路由時(shí),重定向到about。 可以理解為備胎,最后實(shí)在沒(méi)招了,就匹配備胎了。

    const routes = [
        { path: '/about', component: About },
        { path: '/news', component: News },
        {path:'*',redirect:'/about'}//*表示找不到路由時(shí),重定向到about
    ]

    2.6 router-link標(biāo)簽中的tag屬性

    【router-link】默認(rèn)會(huì)轉(zhuǎn)為【a標(biāo)簽】,實(shí)際上可以添加tag屬性來(lái)轉(zhuǎn)為指定的標(biāo)簽,比如轉(zhuǎn)為【buttton標(biāo)簽】或【li標(biāo)簽】等。

    <router-link to="/account/login" tag="button">登錄</router-link>

    不過(guò)vue-router4.x 之后廢棄了 tag 而使用(v-solt)插槽來(lái)實(shí)現(xiàn)

    <router-link custom to="/account/login" custom v-slot="{ isActive,navigate-}">
        <buttton @click="navigate">我是路由自定義標(biāo)簽</buttton>
    </router-link>
    <!-- 
     custom 屬性的意思,就是允許自定義標(biāo)簽,如果不寫(xiě)就會(huì)定義成 a 標(biāo)簽
     navigate 導(dǎo)航的觸發(fā)函數(shù)
     isActive 是否匹配的狀態(tài)
    -->

    3.前端路由嵌套

    如果全是用一級(jí)路由時(shí),路由管理就變得很臃腫,有點(diǎn)亂,路由有父子關(guān)系的話,嵌套路由會(huì)更好。嵌套路由也就是路由中的路由的意思,組件中可以有自己的路由導(dǎo)航和路由容器(router-link、router-view),通過(guò)配置children可實(shí)現(xiàn)多層嵌套,在vue組件中使用<router-view>就可以了。

    舉例:我們上面的例子中,添加一個(gè)books路由,單擊“圖書(shū)”鏈接,以列表的形式顯示所有圖書(shū)的書(shū)名,進(jìn)一步單擊單個(gè)書(shū)名鏈接,在Books視圖中顯示圖書(shū)的詳細(xì)信息。 

    在asssets目錄下新建一個(gè)books.js文件,里面是圖書(shū)數(shù)據(jù)

    export default [
       {id: 1, title: '三體', desc: '三個(gè)天體在互相引力的作用下互相圍繞運(yùn)行,其運(yùn)行軌跡將產(chǎn)生不可預(yù)測(cè)的混沌。'},
       {id: 2, title: '蛤蟆先生去看心理醫(yī)生', desc: '蛤蟆先生一向愛(ài)笑愛(ài)鬧,如今卻一反常態(tài)地郁郁寡歡。'},
       {id: 3, title: '活著', desc: '人是為了活著本身而活著的,而不是為了活著之外的任何事物而活著。'}
    ]

    這里只是為了演示需要,真實(shí)場(chǎng)景中,圖書(shū)數(shù)據(jù)應(yīng)該是通過(guò)ajax請(qǐng)求從服務(wù)器端加載而來(lái)。

    3.1.1. 在父組件中添加導(dǎo)航

    修改Books.vue,以列表方式顯示圖書(shū)數(shù)據(jù),添加導(dǎo)航鏈接,并使用【router-view】來(lái)指定book組件渲染的位置

    <template>
        <div>
            <h4>圖書(shū)列表</h4>
            <ul>
                <li v-for="book in books" :key="book.id">
                    <router-link to="/books/book/">{{book.title}}</router-link>
                </li>
            </ul>
            <!--Book組件在這里渲染-->
            <router-view></router-view>
        </div>
    </template>
    <script>
    import Books from '@/assets/books'
        
     export default {
         data(){
             return {books:Books}
         }
     }
    </script>

    3.1.2.添加子路由顯示的組件

    新建Book.vue,代碼如下。

    <template>
    	<div>
            圖書(shū)詳情頁(yè)面
        </div>
    </template>
    <script>
        export default {
            data(){
                return {
                }
            }
        }
    </script>

    3.1.3.配置父路由的children屬性

    在router目錄下的index.js中修改代碼如下:

    import Book from '@/components/Book'
    //...
    const routes = [
        //...
        {
          path: '/books',
          component: Books,
          children: [
            {path: 'book', component: Book}
          ]
        },
    ]

    (1)要在嵌套的出口(即Books組件中的router-view)中渲染組件,需要在routes選項(xiàng)的配置中使用children選項(xiàng)。children選項(xiàng)只是路由配置對(duì)象的另一個(gè)數(shù)組,如同routes本身一樣,因?yàn)?,可以根?jù)需要繼續(xù)嵌套配置。

    (2)以&lsquo;/&rsquo;開(kāi)頭的嵌套路徑被視為根路徑。上面的子路由導(dǎo)航中,如果path是“/book”則會(huì)出錯(cuò)。

    完成以上步驟后,我們點(diǎn)擊圖書(shū)就可以看到進(jìn)入圖書(shū)詳情頁(yè)面了,但是我們還需要在該頁(yè)面中看到點(diǎn)擊圖書(shū)的詳情信息,這就意味這我們需要將父組件Books.vue中的被點(diǎn)擊圖書(shū)的ID傳遞給Book.vue組件。

    4.路由之間的傳參

    在進(jìn)行表單提交、組件跳轉(zhuǎn)等操作時(shí)需要使用到上一個(gè)表單、組件中的一些數(shù)據(jù)。此時(shí)就需要將參數(shù)在路由間進(jìn)行傳遞。

    4.1.query傳參

    將需要的參數(shù)以 【key = value】的方式放在URL地址中。

    book?id=1

    這里的參數(shù)值“id”可以通過(guò)當(dāng)前組件的表單輸入來(lái)獲取。

    那么進(jìn)入book組件后如何獲取傳入的參數(shù)呢?

    當(dāng)將實(shí)例化的VueRouter對(duì)象掛載到Vue實(shí)例后,Vue Router在Vue實(shí)例上創(chuàng)建了兩個(gè)屬性對(duì)象。即 r o u t e r ( r o u t e r 實(shí) 例 ) 和 router(router實(shí)例)和 router(router實(shí)例)和route(當(dāng)前頁(yè)面的路由信息)。通過(guò)【this.$route.query】可以獲取query查詢參數(shù)。

    <!-- book.vue -->
    <template>
    	<h5>這里是Book頁(yè)面內(nèi)容,獲取參數(shù):{{this.$route.query}},圖書(shū)ID :{{this.$route.query.id}}</h5>
    </template>
    <script>
        export default {
        }
    </script>

    4.2.params方式傳參

    我們也可以使用動(dòng)態(tài)參數(shù)的方式傳遞參數(shù),比如 【book/1】。那【1】分別代表什么?這個(gè)需要在路由中指明。

    <router-link to="/books/book/1">注冊(cè)</router-link>

    與query查詢參數(shù)不同的是,在定義路由信息時(shí),需要以占位符【:參數(shù)名】的方式將需要傳遞的參數(shù)指定到路由地址中,否則系統(tǒng)不能識(shí)別傳遞的參數(shù)。

    在路由中指定參數(shù)的含義,代碼如下:

    children: [{ //books下的子路由
        path: 'book/:id',
        component: Book
    }]

    進(jìn)入Book.vue組件時(shí)如何獲取傳遞過(guò)來(lái)的參數(shù)?這與獲取query參數(shù)的方式相同,可以通過(guò)【 r o u t e 】 獲 取 當(dāng) 前 路 由 信 息 , 通 過(guò) 【 route】獲取當(dāng)前路由信息,通過(guò)【 route】獲取當(dāng)前路由信息,通過(guò)【route.params.參數(shù)名】的方式獲取動(dòng)態(tài)參數(shù)。參數(shù)名也就是在路由中設(shè)置的參數(shù)名(/:后面的)

    <!-- book.vue -->
    <template>
    	<h5>這里是Book頁(yè)面內(nèi)容,獲取參數(shù):{{this.$route.params}},圖書(shū)ID :{{this.$route.params.id}}</h5>
    </template>
    <script>
        export default {
        }
    </script>

    4.3 獲取當(dāng)前路由路徑

    路由對(duì)象還有其他屬性,如【$route.path】,可以獲取當(dāng)前路由的路徑。

    <!-- book.vue -->
    <template>
    	<h5>這里是Book頁(yè)面內(nèi)容,獲取參數(shù):{{this.$route.params}},圖書(shū)ID :{{this.$route.params.id}},路由路徑{{$route.path}}</h5>
    </template>
    <script>
        export default {
        }
    </script>

    4.4 實(shí)現(xiàn)圖書(shū)詳情

    接下來(lái)實(shí)現(xiàn)在Book.vue組件中顯示點(diǎn)擊書(shū)籍的詳細(xì)信息。

    修改Books.vue代碼如下:

    <!-- 注意 to屬性使用了數(shù)據(jù)綁定,才可以使用動(dòng)態(tài)的book.id -->
    <router-link :to="'/books/book/'+book.id">{{book.title}}</router-link>

    修改book.vue代碼如下:

    <template>
        <div>
            <p>圖書(shū)ID:{{ book.id }}</p>
            <p>書(shū)名:{{ book.title }}</p>
            <p>說(shuō)明:{{ book.desc }}</p>
        </div>
    </template>
    <script>
    import Books from '@/assets/books'
    export default {
        data(){
            return {
                book: {}
            }
        },
        //寫(xiě)在created中是為了模擬ajax請(qǐng)求。
        created(){
            this.book = Books.find((item) => item.id == this.$route.params.id);
        }
    }
    </script>

    實(shí)際場(chǎng)景中,當(dāng)單擊某本圖書(shū)鏈接時(shí),應(yīng)該向服務(wù)器端發(fā)起Ajax請(qǐng)求來(lái)獲取圖書(shū)詳細(xì)數(shù)據(jù),于是我們想到在Book組件中通過(guò)生命周期鉤子函數(shù)來(lái)實(shí)現(xiàn),然而,這行不通。這是因?yàn)楫?dāng)兩個(gè)路由都渲染同一個(gè)組件時(shí),例如,從book/1導(dǎo)航到book/2時(shí),vue會(huì)復(fù)用先前的Book實(shí)例,比起銷毀舊實(shí)例再創(chuàng)建新實(shí)例,復(fù)用會(huì)更加高效。但是這就意味著組件的生命周期鉤子不會(huì)再被調(diào)用,所以也就無(wú)法在生命周期鉤子中根據(jù)路由參數(shù)的變化來(lái)實(shí)現(xiàn)更新數(shù)據(jù)。

    要對(duì)同一組件中的路由參數(shù)更改作出響應(yīng),只需監(jiān)聽(tīng)$route對(duì)象。當(dāng)路由參數(shù)變化時(shí),更新圖書(shū)詳細(xì)數(shù)據(jù)。

    Book.vue代碼修改如下:

    created(){
        this.book = Books.find((item) => item.id == this.$route.params.id);
    },
    watch: {
        '$route' (to) {
            this.book = Books.find((item) => item.id == to.params.id);
         }
    }

    (1)只有路由參數(shù)發(fā)生變化時(shí), route 對(duì)象的監(jiān)聽(tīng)器才會(huì)被調(diào)用 ,這意味著第一次渲染Book組件時(shí) ,通過(guò) route對(duì)象的監(jiān)聽(tīng)器才會(huì)被調(diào)用,這意味著第一次渲染Book組件時(shí),通過(guò) route對(duì)象的監(jiān)聽(tīng)器才會(huì)被調(diào)用,這意味著第一次渲染Book組件時(shí),通過(guò)route對(duì)象的監(jiān)聽(tīng)器是得不到數(shù)據(jù)的,因此利用created鉤子來(lái)獲取第一次渲染時(shí)的數(shù)據(jù),當(dāng)然,也可以利用immediate選項(xiàng),將其值設(shè)為true,讓監(jiān)聽(tīng)器在監(jiān)聽(tīng)開(kāi)始后立即執(zhí)行,這樣就不需要created鉤子了。

    watch: {
        '$route': {
            handler: function(to) {
                this.book = Books.find((item) => item.id == to.params.id);
            },
            immediate: true
        } 
    }

    (2)$route對(duì)象的監(jiān)聽(tīng)器函數(shù)中的to參數(shù)表示即將進(jìn)入的目標(biāo)路由對(duì)象,該函數(shù)還可以帶一個(gè)from參數(shù),表示當(dāng)前導(dǎo)航正要離開(kāi)的路有對(duì)象。

    除了監(jiān)聽(tīng)$route對(duì)象,還可以用到后面要學(xué)習(xí)的導(dǎo)航守衛(wèi)。這個(gè)以后再說(shuō)。

    5.編程式導(dǎo)航

    Vue-router路由分為兩種:

    • 聲明式路由編程式路由

    • 聲明式導(dǎo)航是寫(xiě)在template標(biāo)簽里,通過(guò)標(biāo)簽來(lái)觸發(fā)

    編程式導(dǎo)航寫(xiě)在js里,通過(guò)this.$router.push(xxx)來(lái)觸發(fā)路徑

    前面例子中通過(guò)在頁(yè)面上設(shè)置【router-link】標(biāo)簽進(jìn)行路由地址間的跳轉(zhuǎn),就等同于執(zhí)行push方法。

    5.1 $router.push添加 / 跳轉(zhuǎn)路由

    push方法會(huì)將一條心的路由記錄添加到瀏覽器的history棧中,通過(guò)history的自身特性,驅(qū)使瀏覽器進(jìn)行頁(yè)面的跳轉(zhuǎn)。同時(shí),因?yàn)樵趆istory會(huì)話歷史中會(huì)一直保留這個(gè)路由信息,所以當(dāng)后退時(shí)還是可以返回到當(dāng)前的頁(yè)面。

    在push方法中,參數(shù)可以使一個(gè)字符串路徑,或者是一個(gè)描述地址的對(duì)象。

    this.$router.push('/account/register')
    this.$router.push({path:'/account/register'})

    如果帶參數(shù)的話,對(duì)象方式可以通過(guò)query屬性來(lái)指定參數(shù)。

    this.$router.push({
        //想跳到哪里就設(shè)置相應(yīng)的路由,并傳遞參數(shù)信息。比如跳到注冊(cè)頁(yè)面/account/register也行
        path:'/account/login',query:{name:this.name,pwd:this.pwd}
    })

    需求:在登錄頁(yè)面中提供用戶名和密碼輸入框以及【提交】按鈕,點(diǎn)擊【提交】按鈕在注冊(cè)頁(yè)面中顯示出用戶名和密碼信息。

    1.添加tmplogin模板

    <template id="tmplogin">
        <form action="">
            <div>
                <h5>歡迎來(lái)到登錄頁(yè)面,請(qǐng)輸入登錄信息</h5>
                用戶名:<input type="text" name="name" v-model="name" /><br>
                密碼:<input type="password" name="pwd" v-model="pwd" /><br>
                <input type="submit" value="提交" @click="submit">
            </div>
        </form>
    </template>

    2.定義組件對(duì)象

    const login = {
        template: '#tmplogin',
        data: {
            return: {
                name: '',
                pwd: ''
            }
        },
        methods: {
            submit() {
                this.$router.push({
                    //想跳到哪里就設(shè)置相應(yīng)的路由,并傳遞參數(shù)信息。比如跳到注冊(cè)頁(yè)面/account/register也行
                    path:'/account/register',query:{name:this.name,pwd:this.pwd}
                })
            }
        },
    }
    const register = {
                template: '<h5>這里是注冊(cè)頁(yè)面內(nèi)容,獲取傳遞的參數(shù):{{$route.params}},用戶名:{{$route.params.name}},密碼:{{$route.params.pwd}},路由路徑{{$route.path}}</h5>'
    }

    3.在路由中進(jìn)行配置

    children: [{ //account下的子路由
        path: 'login',
        component: login
    }]

    5.2 $router.replace替換路由

    replace方法同樣可以實(shí)現(xiàn)路由跳轉(zhuǎn)的目的。不過(guò),從名字上也可以看出,與使用push方法跳轉(zhuǎn)不同的是,當(dāng)使用replace方法時(shí),并不會(huì)往history棧中新增一條新的記錄,而是會(huì)替換當(dāng)前的記錄,因此無(wú)法通過(guò)后退按鈕返回被替換前的頁(yè)面。

    需求:在賬戶頁(yè)面下添加一個(gè)【替換路由】按鈕,點(diǎn)擊后跳轉(zhuǎn)到新聞頁(yè)面。

    1.tempaccount模板添加button按鈕。

    <button @click="replace">替換路由</button>

    2.在Account組件下,綁定對(duì)應(yīng)方法。

    var Account = {
        template: '#tmpaccount', //這里模板內(nèi)容變復(fù)雜了,所以單獨(dú)定義
        methods:{
            replace(){
                this.$router.replace({
                    path:'/news'
                })
            }
        }
    }

    從【關(guān)于我們】到【賬戶】,點(diǎn)擊按鈕跳轉(zhuǎn),進(jìn)入【新聞】,此時(shí)點(diǎn)擊瀏覽器的后退,發(fā)現(xiàn)并不會(huì)回到【賬戶】,而是回到【關(guān)于我們】。

    5.3 $router.go()跳轉(zhuǎn)

    當(dāng)使用go方法時(shí),可以在history記錄中向前或向后跳轉(zhuǎn)。也就是說(shuō),通過(guò)go方法可以在已經(jīng)存儲(chǔ)的history路由歷史中前進(jìn)后退。

    //在歷史記錄中前進(jìn)一步,等同于 history.forward()
    this.$router.go(1);
    //后退一步,等同于history.back()
    this.$router.go(-1);
    //前進(jìn)兩步記錄
    this.$router.go(2);

    5.4 router 與 router與 router與route的區(qū)別

    1.$router對(duì)象是全局路由的實(shí)例,是VueRouter構(gòu)造方法的實(shí)例。是路由操作對(duì)象,可以添加或跳轉(zhuǎn)路由,替換路由等。

    2.$route對(duì)象表示當(dāng)前的路由信息,包含了當(dāng)前 URL 解析得到的信息。包含當(dāng)前的路徑,參數(shù),query對(duì)象等。

    6.命名路由和命名試圖

    6.1 命名路由

    在某些時(shí)候,生成的路由URL地址可能會(huì)很長(zhǎng),在使用中可能會(huì)顯得有些不便。這個(gè)時(shí)候通過(guò)一個(gè)名稱來(lái)標(biāo)識(shí)路由會(huì)更方便一些。

    const routes = [
        { path: '/about',name:'aa', component: About }
    ]

    使用命名路由之后,在使用router-link的to屬性跳轉(zhuǎn)路由的時(shí)候傳一個(gè)對(duì)象,跳轉(zhuǎn)到指定的路由地址上。

    <router-link :to="{name:'aa'}">關(guān)于我們</router-link>

    6.2 命名視圖

    當(dāng)打開(kāi)一個(gè)頁(yè)面時(shí),整個(gè)頁(yè)面可能是由多個(gè)Vue組件構(gòu)成的。例如,一般后端管理首頁(yè)可能是由sidebar(側(cè)導(dǎo)航),header(頂部導(dǎo)航)和main(主內(nèi)容)這三個(gè)Vue組件構(gòu)成的。此時(shí),通過(guò)Vue Router構(gòu)建路由信息時(shí),如果一個(gè)URL只能對(duì)應(yīng)一個(gè)Vue組件,整個(gè)頁(yè)面將無(wú)法正確顯示。

    通過(guò)router-view標(biāo)簽,就可以指定組件渲染顯示到什么位置。因此,當(dāng)需要在一個(gè)頁(yè)面上顯示多個(gè)組件的時(shí)候,就需要在頁(yè)面中添加多個(gè)router-view標(biāo)簽。

    那么,是不是可以通過(guò)一個(gè)路由對(duì)應(yīng)多個(gè)組件,然后按需渲染到不同的【router-view】標(biāo)簽上呢?默認(rèn)情況下不能,當(dāng)我們將一個(gè)路由對(duì)象對(duì)應(yīng)到多個(gè)組件時(shí),不管有多少個(gè)【router-view】標(biāo)簽,程序都會(huì)將第一個(gè)組件渲染到所有的【router-view】標(biāo)簽上。

    那怎么辦呢?需要實(shí)現(xiàn)的是一個(gè)路由信息可以通過(guò)設(shè)計(jì)者的需求去渲染到頁(yè)面中指定的router-view標(biāo)簽,這可以通過(guò)Vue Router命名視圖的方式來(lái)實(shí)現(xiàn)。

    命名視圖與命名路由的實(shí)現(xiàn)方式相似。命名視圖通過(guò)在【router-view】標(biāo)簽上設(shè)定name屬性,然后再構(gòu)建路由與組件的對(duì)應(yīng)關(guān)系時(shí),以一種【name:component】的形式構(gòu)造出一個(gè)組件對(duì)象,從而指明在哪個(gè)【router-view】標(biāo)簽上加載什么組件。

    1.三個(gè)組件的樣式布局

    .container{
        height: 500px;
    }
    .top {
        background-color:beige;
        width: 100%;
        height: 80px;
    }
    .left{
        float: left;
        width: 20%;
        height: 100%;
        background-color: burlywood;
    }
    .right{
        float: left;
        width: 80%;
        height: 100%;
        background-color: aquamarine;
    }

    2.html代碼部分

    const header = {
        template: '<div class="header"> header </div>'
    }   
    const sidebar = {
        template: '<div class="sidebar">sidebar</div>'
    }    
    const main = {
        template: '<div class="main"> main </div>'
    }

    3.定義路由跳轉(zhuǎn)的組件模板

    const header = {
        template: '<div class="header"> header </div>'
    }   
    const sidebar = {
        template: '<div class="sidebar">sidebar</div>'
    }    
    const main = {
        template: '<div class="main"> main </div>'
    }

    4.定義路由信息

    const routes = [{
        path: '/',    //一個(gè)路由對(duì)應(yīng)多個(gè)組件
        components: {
            default: header,//指定什么router-view顯示對(duì)應(yīng)的組件,即指明是在哪個(gè) router-view 標(biāo)簽上加載什么組件。
            sidebar: sidebar,//格式name:component,name為router-view的name
            main: main
        }
    }]

    完整代碼

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="js/vue.js"></script>
        <script src="js/vue-router.js"></script>
        <style>
            .container{
                height: 500px;
            }
            .top {
                background-color:beige;
                width: 100%;
                height: 80px;
            }
            .left{
                float: left;
                width: 20%;
                height: 100%;
                background-color: burlywood;
            }
            .right{
                float: left;
                width: 80%;
                height: 100%;
                background-color: aquamarine;
            }
        </style>
    <body> 
        <div id="app">
            <div class="top">
                <!-- 在 router-view 中,默認(rèn)的 name 屬性值為 default -->
                <router-view></router-view>
            </div>       
            <div class="container">
                <div class="left">
                    <router-view name="sidebar"></router-view>
                </div>
                <div class="right">
                    <router-view name="main"></router-view>
                </div>           
            </div>
        </div>    
        <template id="sidebar">
            <div class="sidebar">
                sidebar
            </div>
        </template>    
        <script>
            // 1、定義路由跳轉(zhuǎn)的組件模板
            const header = {
                template: '<div class="header"> header </div>'
            }   
            const sidebar = {
                template: '#sidebar'
            }    
            const main = {
                template: '<div class="main"> main </div>'
            }   
            // 2、定義路由信息
            const routes = [{
                path: '/',    //一個(gè)路由對(duì)應(yīng)多個(gè)組件
                components: {
                    default: header,//指定什么router-view顯示對(duì)應(yīng)的組件,即指明是在哪個(gè) router-view 標(biāo)簽上加載什么組件。
                    sidebar: sidebar,//格式name:component,name為router-view的name
                    main: main
                }
            }]    
            const router = new VueRouter({
                routes
            })    
            // 3、掛載到當(dāng)前 Vue 實(shí)例上
            const vm = new Vue({
                el: '#app',
                data: {},
                methods: {},
                router: router
            });
        </script>
    </body>
    </html>

    7.組件與路由間的解耦

    在前面所講路由傳遞參數(shù)的辦法中,不管是query傳參還是param傳參,最終都是通過(guò)this.$route屬性獲取參數(shù)信息,如$route.query.name或$route.params.name

    這意味著組件和路由耦合到了一塊,所有需要獲取參數(shù)值的地方都需要加載VueRouter。那么如何實(shí)現(xiàn)組件與路由的解耦呢?

    在之前學(xué)習(xí)組件相關(guān)知識(shí)時(shí),我們知道可以通過(guò)組件的props選項(xiàng)來(lái)實(shí)現(xiàn)子組件接受父組件傳遞的值。在Vue Router中,可以通過(guò)使用組件的props選項(xiàng)來(lái)進(jìn)行組件與路由之間的解耦。

    7.1 設(shè)置props:true情況

    1.在定義路由規(guī)則時(shí),指定props的屬性為true。

    ```bash
    //定義路由      
    const router = new VueRouter({
        routes: [{   //定義路由 
            path: '/myRouter/:id', //路由規(guī)則通過(guò)占位符指明傳遞的參數(shù)為id,同時(shí)id要為上面組件props選項(xiàng)中有的值
            component: mycomp,
            props: true //此處props要設(shè)置為true,即可以實(shí)現(xiàn)組件與Vue Router之間的解耦
        }]
    })

    2.在定義組件時(shí),指定props接受的參數(shù)

    //定義組件
    const mycomp = {
        props: ['id'],
        //此處沒(méi)有通過(guò)$route.params.id方式獲取參數(shù)id,也就不需要router實(shí)例
        template: '<h4>組件獲取到了路由傳遞的參數(shù):{{id}},但此處并沒(méi)有通過(guò)$route去獲取。 </h4>' /
    }

    完整核心代碼如下:

    <style>
        .container {
            background-color:blanchedalmond;
            margin-top: 10px;
            width: 600px;
            height: 300px;
        }
    </style>
    <body>
        <div id="app">
            <button type="button" @click="goMethod">路由與組件解綁示例1</button>
            <div class="container">
                <router-view></router-view>
            </div>
        </div>
        <script>
            //定義組件
            const mycomp = {
                props: ['id'],
                template: '<h4>組件獲取到了路由傳遞的參數(shù):{{id}},但此處并沒(méi)有通過(guò)$route去獲取。 </h4>' //此處沒(méi)有通過(guò)$route.params.id方式獲取參數(shù)id,也就不需要router實(shí)例
            }  
            //定義路由      
            const router = new VueRouter({
                routes: [{   //定義路由 
                    path: '/myRouter/:id', //路由規(guī)則通過(guò)占位符指明傳遞的參數(shù)為id,同時(shí)id要為上面組件props選項(xiàng)中有的值
                    component: mycomp,
                    props: true //此處props要設(shè)置為true,即可以實(shí)現(xiàn)組件與Vue Router之間的解耦
                }]
            })
            const vm = new Vue({
                el: '#app',
                data: {},
                methods: {
                    goMethod() { //該方法實(shí)現(xiàn)路由跳轉(zhuǎn),跳轉(zhuǎn)到myRouter,并傳入?yún)?shù)123
                        this.$router.push({
                            path: '/myRouter/123' //param方式傳參
                        })
                    }
                },
                router
            })
        </script>
    </body>

    需要注意的是,該方法要求路由傳遞參數(shù)方式一定為param方式。

    7.2 設(shè)置props為對(duì)象情況

    在將路由規(guī)則的props屬性定義為對(duì)象后,不管路由參數(shù)中傳遞的是什么值,最終獲取的都是對(duì)象中的值。同時(shí),需要注意的是,props中的屬性值必須是靜態(tài)的,固定的。

    上述案例修改下定義路由部分的代碼

    //定義路由      
    const router = new VueRouter({
        routes: [{   //定義路由 
            path: '/myRouter/:id', //路由規(guī)則通過(guò)占位符指明傳遞的參數(shù)為id,同時(shí)id要為上面組件props選項(xiàng)中有的值
            component: mycomp,
            props:{
                id:'123' //組件獲取到的是這里的值
            }
        }]
    })

    與上面案例相比,html與js沒(méi)有變化,只需要修改下js部分

    //定義組件
    const mycomp = {
        props: ['id'],
        template: '<h4>組件獲取到了路由傳遞的參數(shù):{{id}},但此處并沒(méi)有通過(guò)$route去獲取。 </h4>' 
    }  
    //定義路由      
    const router = new VueRouter({
        routes: [{   //定義路由 
            path: '/myRouter/:id', //路由規(guī)則通過(guò)占位符指明傳遞的參數(shù)為id,同時(shí)id要為上面組件props選項(xiàng)中有的值
            component: mycomp,
            props:{
                id:'123' //組件獲取到的是這里的值
            }
        }]
    })
    const vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            goMethod() { //該方法實(shí)現(xiàn)路由跳轉(zhuǎn),跳轉(zhuǎn)到myRouter
                this.$router.push({
                    path: '/myRouter/123456'//param方式傳參,隨便寫(xiě)參數(shù),但是必須有
                })
            }
        },
        router
    })

    7.3 設(shè)置props為函數(shù)情況

    在對(duì)象模式中,只能接受靜態(tài)的props屬性值。而使用函數(shù)模式之后,就可以對(duì)靜態(tài)值做數(shù)據(jù)的進(jìn)一步交工,或者是與路由傳遞參數(shù)的值進(jìn)行結(jié)合。

    js部分代碼修改如下

    //定義組件
    const mycomp = {
        props: ['id', 'name'],
        template: '<h4>組件獲取到了路由傳遞的參數(shù):{{id}}——{{name}},但此處并沒(méi)有通過(guò)$route去獲取。 </h4>' 
    }
    //定義路由      
    const router = new VueRouter({
        routes: [{   //定義路由 
            path: '/myRouter', 
            component: mycomp,
            props: route => ({
                id: route.query.id,//獲取到通過(guò)路由傳遞的參數(shù),這個(gè)就可以是動(dòng)態(tài)的
                name: 'zhangsan'//這個(gè)是靜態(tài)的
            })
        }]
    })
    const vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            goMethod() { //該方法實(shí)現(xiàn)路由跳轉(zhuǎn),跳轉(zhuǎn)到myRouter
                this.$router.push({
                    path: '/myRouter?id=123'//query方式傳參
                })
            }
        },
        router
    })

    到此,相信大家對(duì)“vue獲取參數(shù)的方式有哪些”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    vue
    AI