三十分鐘學會使用vue-router搭建單頁應用(SPA)

一、什么是單頁應用

單頁web應用(single page web application,SPA),就是只有一張Web頁面的應用。單頁應用程序 (SPA) 是加載單個HTML 頁面并在用戶與應用程序交互時動態更新該頁面的Web應用程序。瀏覽器一開始會加載必需的HTML、CSS和JavaScript,所有的操作都在這張頁面上完成,都由JavaScript來控制。因此,對單頁應用來說模塊化的開發和設計顯得相當重要。

二、單頁應用的優勢和缺點

【1】優勢

  • ** 操作體驗流暢:**媲美本地應用的感覺,切換過程中不會頻繁有被“打斷”的感覺。因為界面框架都在本地,與服務端的通訊基本只有數據,所以便于遷移,可以用比較小的代價,遷移成桌面產品,或者各種移動端Hybrid產品。
  • ** 完全的前端組件化:**前端開發不再以頁面為單位,更多地采用組件化的思想,代碼結構和組織方式更加規范化,便于修改和調整;
  • ** API 共享:**如果你的服務是多端的(瀏覽器端、Android、iOS、微信等),單頁應用的模式便于你在多個端共用 API,可以顯著減少服務端的工作量。容易變化的 UI 部分都已經前置到了多端,只受到業務數據模型影響的 API,更容易穩定下來,便于提供更棒的服務;
  • 組件共享:在某些對性能體驗要求不高的場景,或者產品處于快速試錯階段,借助于一些技術(HybridReact Native),可以在多端共享組件,便于產品的快速迭代,節約資源。

【2】缺點

  • 首次加載大量資源:要在一個頁面上為用戶提供產品的所有功能,在這個頁面加載的時候,首先要加載大量的靜態資源,這個加載時間相對比較長;不過可以利用路由懶加載解決這個問題
  • ** 對搜索引擎不友好:**因為界面的絕大部分都是動態生成的,所以搜索引擎很不容易索引它。
  • 開發難度相對較高:開發者的JavaScript技能必須過關,同時需要對組件化、設計模式有所認識,他所面對的不再是一個簡單的頁面,而是一個運行在瀏覽器環境中的桌面軟件。

三、vue-router是什么

    vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,適合用于構建單頁面應用。vue的單頁面應用是基于路由和組件的,路由用于設定訪問路徑,并將路徑和組件映射起來。傳統的頁面應用,是用一些超鏈接來實現頁面切換和跳轉的。在vue-router單頁面應用中,則是路徑之間的切換,也就是組件的切換。**路由模塊的本質 就是建立起url和組件之間的映射關系**。

    至于我們為啥不能用a標簽,這是因為用Vue做的都是單頁應用(當你的項目npm run build 打包后,就會生成dist文件夾,這里面只有靜態資源和一個index.html頁面),所以你寫的<a></a>標簽跳轉頁面是不起作用的,你必須使用vue-router來進行管理。

四、安裝vue-router

npm install vue-router -mages.ages/2334.oorient/strip) 

五、配置和簡單使用vue-router

【1】在src文件夾下新增一個router文件夾,里面添加一個index.js文件

【2】在main.js文件中引入

【3】router文件下的index.js配置

import Vue from 'vue'
import Router from 'vue-router'

// 引入page1和page2組件
import page1 from '@/components/page1'
import page2 from '@/components/page2'

Vue.use(Router)

export default new Router({
  // 定義路由,每個路由應該映射一個組件,component對應引入的組件名
  routes: [
    {
      path: '/page1',
      name: 'page1',
      component: page1
    },
    {
      path: '/page2',
      name: 'page2',
      component: page2
    },
  ]
})

【4】使用

我們己經配置好了路由/page1和/page2,可以在app.vue頁面使用這兩個路由

<template>
  <div id="app">
    <!-- 
      1、使用router-link標簽來導航 
      2、通過傳入 `to` 屬性指定鏈接
      3、<router-link> 默認會被渲染成一個 `<a>` 標簽
      4、當<router-link>對應的路由匹配成功,將自動設置class屬性值為.router-link-active
    -->
    <router-link to="/page1">page1</router-link>

    <!-- 通過路由設置的name值進行導航 -->
    <router-link :to="{name: 'page2'}">page2</router-link>

    <!-- 使用編程式導航 -->
    <span @click="gotoPage1">gotoPage1</span>

    <!-- 占坑,路由匹配到的組件將渲染在這里 -->
    <router-view />
  </div>
</template>

<script>
  export default {
    methods: {
      gotoPage1() {
        // 編程式導航
        this.$router.push('/page1')
      }
    },
  }
</script>

【5】效果

六、this.router 和 this.route的區別

【1】router:是VueRouter的實例,相當于一個全局的路由器對象,里面含有很多屬性和子對象,例如history對象,編程式路由導航可以使用this.$router.push進行跳轉。

【2】route:相當于當前路由對象,可以從里面獲取name,path,params,query等

七、動態路由

【1】官方解釋

動態路徑參數,使用冒號 : 標記。當匹配到一個路由時,參數值會被設置到this.$route.params,可以在每個組件內使用。

你可以在一個路由中設置多段“路徑參數”,對應的值都會設置到$route.params中。

【2】適用場景

比如商品詳情頁面,頁面結構都一樣,只是商品id的不同,所以這個時候就可以用動態路由。

配置動態路由參數

// 配置路由
const router = new VueRouter({
  routes: [
    // 動態路徑參數 以冒號開頭
    { path: '/goods/:id', component: goods}
  ]
})

goods組件

  <template>
    <div>
      當前商品id為:{{$route.params.id}}
    </div>
  </template>

在瀏覽器地址欄中輸入/goods/123

八、嵌套路由

嵌套路由就是路由里面嵌套他的子路由,子路由關鍵屬性children

每一個子路由里面可以嵌套多個組件,子組件又有路由導航和路由容器

舉例:假設page頁面下包含home子組件和goods子組件

配置嵌套路由(在page路由下增加一個children屬性,配置home和goods兩個子組件路由)

export default new Router({
  // 定義路由,每個路由應該映射一個組件,component對應引入的組件名
  routes: [
    {
      path: '/page',
      name: 'page',
      component: page,
      children: [{
        path: '/page/home',
        name: 'home',
        component: home,
      }, {
        path: '/page/goods',
        name: 'goods',
        component: goods,
      }]
    },
    {
      path: '/page2',
      name: 'page2',
      component: page2
    },
  ]
})

page組件配置

<template>
  <div>
    <p>page組件</p>
    <router-link to="/page/home">home</router-link>
    <router-link to="/page/goods">goods</router-link>

    <!-- 占坑,匹配的子組件將渲染在這里 -->
    <router-view></router-view>
  </div>
</template>

效果

九、編程式導航

【1】router.push

點擊 <router-link :to="..."> 等同于調用 this.$router.push(...)

在 Vue 實例內部,你可以通過 router訪問路由實例,因此你可以調用 this.router.push

聲明式 編程式
<router-link :to="..."> router.push(...)

$router.push(...)的參數可以是一個字符串路徑,或者一個描述地址的對象。例如:

        // 字符串
        router.push('home')

        // 對象
        router.push({ path: 'home' })

        // 命名的路由
        router.push({ name: 'user', params: { userId: '123' } })

        // 帶查詢參數,變成 /register?plan=private
        router.push({ path: 'register', query: { plan: 'private' } })

        // 注意:如果提供了path,params會被忽略。需要提供路由的name或手寫完整的帶有參數的path
        const userId = '123'
        router.push({ path: '/user', params: { userId }}) // -> /user params不生效
        router.push({ name: 'user', params: { userId }}) // -> /user/123 params生效
        router.push({ path: `/user/${userId}` }) // -> /user/123 params生效

【2】router.replace

跟 router.push 很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 一一 替換掉當前的 history 記錄。

【3】router.go(n)

這個方法的參數是一個整數,意思是在 history 記錄中向前或者后退多少步,類似window.history.go(n)

// 在瀏覽器記錄中前進一步,等同于 history.forward()
router.go(1)

// 后退一步記錄,等同于 history.back()
router.go(-1)

// 前進 3 步記錄
router.go(3)

// 后退 3 步記錄
router.go(-3)

十、命名路由

就是在routers配置路由的時候加一個name屬性,通過name名稱來標識一個路由更加方便一些,特別是在嵌套路由path名稱特別長的時候

export default new Router({
  routes: [
    {
      path: '/page',
      name: 'page',
      component: page,
      children: [{
        path: '/page/home',
        name: 'home',
        component: home,
      }]
    },
  ]
})

以下四種方式都可以導航到/page/home路徑

    <router-link to="/page/home">home</router-link>
    <router-link :to="{name: home}">home</router-link>
    this.$router.push('/page/home')
    this.$router.push({name: home})

十一、命名視圖

簡單來說就是,給不同的router-view定義不同的名字,通過名字進行對應組件的渲染。如果router-view沒有設置名字,那么默認為default。

【1】適用場景

例如創建一個布局,有 topNav(頂部導航)、sidebar (側導航) 和 main (主要內容) 三個視圖,這個時候命名視圖就派上用場了。

配置路由:根路由下定義了三個組件

index(主內容):映射在router-view 默認視圖上

topNav(頂部導航):映射在 router-view 的 name 為 top 的視圖上

sideNav(側邊欄):映射在 router-view 的 name 為 side 的視圖上

export default new Router({
  routes: [
    {
      path: '/',
      components: {
        default: Index,
        side: SideNav,
        top: TopNav,
      },
      children: [{
        path: '/home',
        component: Home,
      }, {
        path: '/goods',
        component: Goods,
      }]
    },
  ]
})

App.vue文件(添加name屬性創建兩個命名視圖和一個default默認視圖)

    <router-view class="view one" name="top"></router-view>
    <router-view class="view two" name="side"></router-view>
    <router-view class="view three"></router-view>

效果

十二、重定向和別名

【1】重定向(redirect****)

/a的重定向是/b,當用戶訪問 /a 時,URL 將會被替換成 /b,然后導航到 /b 頁面

    // 重定向目標可以是一個path
    { path: '/a', component: A, redirect: '/b',  },

    // 重定向目標也可以是一個命名的路由
    { path: '/a', component: A, redirect: {name: 'b'}},

    // 甚至是一個方法
    { path: '/a', component: A, redirect: to => {
      // 方法接收目標路由to作為參數 to包含hash、params、query等屬性
      // return 重定向的字符串路徑/路徑對象
      return '/b'
    }}

【2】別名(alias)

/a 的別名是 /b,意味著,當用戶訪問 /b 時,URL 會保持為 /b,但是導航到 /a頁面,就像用戶訪問 /a 一樣。

  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]

十三、vue-router模式

【1】hash (默認)

hash模式URL:http://www.abc.com/#/hello

hash即地址欄 URL 中的 # 符號,比如這個 URL:http://www.abc.com/#/hello,hash 的值為 #/hello。它的特點在于hash 雖然出現在 URL 中,但不會被包括在 HTTP 請求中,對后端完全沒有影響,因此改變 hash 不會重新加載頁面。

【2】history

history模式URL:http://www.abc.com/hello

有的時候出于強迫癥,不能忍受模式下的URL上存在#符號,或者是出于業務需求,URL不能帶#號。這個時候要考慮采用vue-router的history模式,history模式的前端配置與上文大同小異,但是由于history模式下URL 路徑的跳轉是vue-router利用h5的history API動態添加的,而手動刷新頁面會導致找不到路由從而產生404錯誤,因此還需要對服務端進行配置,將路由重定向到一級頁面

【3】模式配置

export default new Router({
  mode: 'history',
  routes: [...]
})

十四、路由守衛

Vue - 路由守衛(路由的生命周期)

文章每周持續更新,可以微信搜索「 前端大集錦 」第一時間閱讀,回復【視頻】【書籍】領取200G視頻資料和30本PDF書籍資料

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374