一、前言 前端路由是什麼?如果你之前從事的是後端的工作,或者雖然有接觸前端,但是並沒有使用到單頁面應用的話,這個概念對你來說還是會很陌生的。那麼,為什麼會在單頁面應用中存在這麼一個概念,以及,前端路由與我們後端的路由有什麼異同呢。本章,我們就來簡單介紹下前端路由的概念,以及如何在 Vue 中使用 V ...
一、前言
前端路由是什麼?如果你之前從事的是後端的工作,或者雖然有接觸前端,但是並沒有使用到單頁面應用的話,這個概念對你來說還是會很陌生的。那麼,為什麼會在單頁面應用中存在這麼一個概念,以及,前端路由與我們後端的路由有什麼異同呢。本章,我們就來簡單介紹下前端路由的概念,以及如何在 Vue 中使用 Vue Router 來實現我們的前端路由。
學習系列目錄地址:https://www.cnblogs.com/danvic712/p/9549100.html
倉儲地址:https://github.com/Lanesra712/VueTrial/blob/master/chapter02-bronze/router/sample.html
二、乾貨合集
在傳統的多頁面應用中,網站的每一個 URL 地址都是對應於伺服器磁碟上的一個實際物理文件。例如,當我們訪問 https://www.yousite.com/index.html 這個網址的時候,伺服器會自動把我們的請求對應到當前站點路徑下麵的 index.html 文件,然後再給予響應,將這個文件返回給瀏覽器。當我們跳轉到別的頁面上時,毫無疑問則會再重覆一遍上面的過程。
但是在單頁面應用中,整個項目中只會存在一個 html 文件,當用戶切換頁面時,只是通過對這個唯一的 html 文件進行動態重寫,從而達到響應用戶的請求。也就是說,從切換頁面這個角度上說,應用只是在第一次打開時請求了伺服器(非服務端渲染的單頁應用)。
因為訪問的頁面是並不真實存在的,所以如何正確的在一個 html 文件中展現出用戶想要訪問的信息就成為單頁面應用需要考慮的問題,而對於這一路由問題的解決方案,為了與我們後端傳統意義上的路由進行區別,就將此稱為前端路由。
1、前端路由的實現方式
目前的前端路由的實現方式主要是通過 hash 路由匹配或者是採用 html5 中的 history api 這兩種,也就是說,不管是 hash 路由還是使用 history 路由模式,其實都是基於瀏覽器自身的特性。
hash 路由:hash 這個概念,可能聽起來有些陌生,不過,其實我們在之前的前端開發中,其實是有所接觸的。例如,在某些情況下,我們需要定位頁面上的某些位置,就像下麵的例子中展現的那樣,我想要通過點擊不同的按鈕就跳轉到指定的位置,這裡我們使用的錨點定位其實就是 hash。
<div id="content"> <div class="btn-container"> <a class="btn" href="#image1">圖片1</a> <a class="btn" href="#image2">圖片2</a> </div> <img src="./xxx/xxx.jpg" id="image1"> <img src="./xxx/xxx.jpg" id="image2"> </div>
hash 路由的本質是瀏覽器 location 對象中的 hash 屬性,它會記錄鏈接地址中 '#' 後面的內容(e.g.:#part1)。因此,我們可以通過監聽 window.onhashchange 事件獲取到跳轉前後訪問的地址,從而實現地址切換的目的。
history 路由:在之前的 html 版本中,我們可以通過 history.back(), history.forward()和 history.go() 方法來完成在用戶歷史記錄中向後和向前的跳轉。而 history 路由則是使用了 html5 中新增的 pushState 事件和 replaceState() 事件。
通過這兩個新增的 API,就可以實現無刷新的更改地址欄鏈接,配合 AJAX 就可以做到整個頁面的無刷新跳轉,具體實現的原理大家可以看看這篇文章 =》https://www.renfei.org/blog/html5-introduction-3-history-api.html
在 Vue 中,Vue Router 是官方提供的路由管理器。它和 Vue.js 的核心深度集成,因此,不管是採用 hash 的方式還是使用 history api 實現我們的前端路由都有很好的支持,所以這裡我們採用 Vue Router 這一組件來實現我們的前端路由。
2、路由實現
首先我們需要將 Vue Router 添加引用到我們的項目中,這裡我還是採用直接引用 js 文件的方式為我們的示例代碼添加前端路由支持。
在 Vue 中使用 Vue Router 構建單頁面應用,我們只需要將組件 (components) 映射到定義的路由 (routes) 規則中,然後告訴 Vue Router 在哪裡渲染它們,並將這個路由配置掛載到 Vue 實例節點上即可。
在 Vue Router 中,我們使用 router-link 標簽來渲染鏈接,當然,預設生成的是 a 標簽,如果你想要將路由信息生成別的 html 標簽,則可以使用 tag 屬性指明需要生成的標簽類型。
<!-- 預設渲染成 a 標簽 --> <router-link to="/home">主頁</router-link> <!-- 渲染成 button 標簽 --> <router-link to="/home" tag="button">主頁</router-link>
可以看到,當我們指定 tag 屬性為 button 後,頁面渲染後的的標簽就變成了 button 按鈕。同樣的,它還是會監聽點擊,觸發導航。
同時,從上圖可以看出,當前的鏈接地址為 #/home,也就是說,通過 router-link 生成的標簽,當頁面地址與對應的路由規則匹配成功後,將自動設置 class 屬性值為 .router-link-active。當然,我們也可以通過指定 active-class 屬性或者在構造 VueRouter 對象時使用 linkActiveClass 來自定義鏈接激活時使用的 CSS 類名。
<!-- 使用屬性來設定自定義激活類名 --> <router-link to="/home" active-class="aaaa">主頁</router-link> <!-- 在構造對象時設定全局預設類名 --> const router = new VueRouter({ routes: [], linkActiveClass: 'aaaaa' })
當路由表構建完成後,對於指向路由表中的鏈接,需要在頁面上找一個地方去顯示已經渲染完成後的組件,這時,我們就需要使用 router-view 標簽去告訴程式,我們需要將渲染後的組件顯示在當前位置。
在下麵的示例代碼中,模擬了 Vue 中路由的使用,當訪問 #/home 時會進行載入 home 組件,而當鏈接跳轉到 #/account 時則會載入 account 組件。同時,我們可以發現,在 account 組件中又包含了兩個子路由,通過點擊 account 組件中的子路由地址,從而載入對應的 login 組件和 register 組件。
<script src="../../lib/vue.js"></script> <script src="../../lib/vue-router.js"></script> <style> .container { background-color: aquamarine; margin-top: 20px; width: 740px; height: 300px; } </style> <div id="app"> <!-- 通過 router-link 標簽來生成導航鏈接 --> <router-link to="/home">主頁</router-link> <router-link to="/account">賬戶</router-link> <div class="container"> <!-- 將選中的路由渲染到 router-view 下--> <router-view></router-view> </div> </div> <template id="tmpl"> <div> <h3> account page </h3> <!-- 生成嵌套子路由地址 --> <router-link to="/account/login">登錄</router-link> <router-link to="/account/register">註冊</router-link> <!-- 生成嵌套子路由渲染節點 --> <router-view></router-view> </div> </template> <script> // 1、定義路由跳轉的組件模板 const home = { template: '<div> home page </div>' } const account = { template: '#tmpl' } const login = { template: '<div> login page</div>' } const register = { template: '<div> register page</div>' } // 2、定義路由信息 const routes = [{ path: '/', redirect: '/home' }, { path: '/home', component: home }, { path: '/account', component: account, children: [{ path: 'login', component: login }, { path: 'register', component: register } ] } ] const router = new VueRouter({ //mode: 'history', //使用 history 模式還是 hash 路由模式 routes }) // 3、掛載到當前 Vue 實例上 const vm = new Vue({ el: '#app', data: {}, methods: {}, router: router }); </script>
在上面的代碼中,也使用到了嵌套路由和路由的重定向。通過使用路由重定向,我們可以將用戶訪問網站的根目錄 / 時進行重定向到 /home ,而嵌套路由則可以將 URL 中各段動態路徑也按某種結構對應到實際嵌套的各層組件。
例如,這裡的 login 組件和 register 組件,它們都是位於 account 組件中的,因此,在構建 url 時,我們應該將該地址位於 /account url 後面,從而更好地表達這種關係。所以這裡,我們在 account 組件中又添加了一個 router-view 標簽,用來渲染出嵌套的組件內容。同時,通過在定義 routes 時在參數中使用 children 屬性,從而達到配置嵌套路由信息的目的。
PS:以 / 開頭的嵌套路徑會被當作根路徑,而我們的 login 組件和 register 組件都是包含在 account 中,所以這裡直接定義 path 參數即可。
三、總結
這一章主要是介紹瞭如何使用 Vue Router 在 Vue 中構建我們的前端路由。在實際開發中,對於一個路徑,可能會對應到多個組件,這時,如何將多個組件綁定到一個路徑下,就是我們需要解決的問題。另外,在實際使用中我們會遇到路由傳參,可能會因為 hash 路由不漂亮,從而準備採用 history 路由,對於這些需求的實現,將放在下一章中進行學習。