一、什么是單頁應用
單頁web應用(single page web application,SPA),就是只有一張Web頁面的應用。單頁應用程序 (SPA) 是加載單個HTML 頁面并在用戶與應用程序交互時動態更新該頁面的Web應用程序。瀏覽器一開始會加載必需的HTML、CSS和JavaScript,所有的操作都在這張頁面上完成,都由JavaScript來控制。因此,對單頁應用來說模塊化的開發和設計顯得相當重要。
二、單頁應用的優勢和缺點
【1】優勢
- ** 操作體驗流暢:**媲美本地應用的感覺,切換過程中不會頻繁有被“打斷”的感覺。因為界面框架都在本地,與服務端的通訊基本只有數據,所以便于遷移,可以用比較小的代價,遷移成桌面產品,或者各種移動端Hybrid產品。
- ** 完全的前端組件化:**前端開發不再以頁面為單位,更多地采用組件化的思想,代碼結構和組織方式更加規范化,便于修改和調整;
- ** API 共享:**如果你的服務是多端的(瀏覽器端、Android、iOS、微信等),單頁應用的模式便于你在多個端共用 API,可以顯著減少服務端的工作量。容易變化的 UI 部分都已經前置到了多端,只受到業務數據模型影響的 API,更容易穩定下來,便于提供更棒的服務;
- 組件共享:在某些對性能體驗要求不高的場景,或者產品處于快速試錯階段,借助于一些技術(Hybrid、React 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.
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.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: [...]
})
十四、路由守衛
文章每周持續更新,可以微信搜索「 前端大集錦 」第一時間閱讀,回復【視頻】【書籍】領取200G視頻資料和30本PDF書籍資料