認識vue-router**
vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,適合用於構建單頁面應用。
我們可以訪問其官方網站對其進行學習: https://router.vuejs.org/zh/
vue-router是基於路由和組件的
路由用於設定訪問路徑, 將路徑和組件映射起來.
在vue-router的單頁面應用中, 頁面的路徑的改變就是組件的切換.
安裝和使用vue-router
步驟一: 安裝vue-router
npm install vue-router --save
步驟二: 在模塊化工程中使用它(因為是一個插件, 所以可以通過Vue.use()來安裝路由功能)
第一步:導入路由對象,並且調用 Vue.use(VueRouter)
第二步:創建路由實例,並且傳入路由映射配置
第三步:在Vue實例中掛載創建的路由實例
使用vue-router的步驟:
第一步: 創建路由組件
第二步: 配置路由映射: 組件和路徑映射關系
第三步: 使用路由: 通過 <router-link>
和 <router-view>
-
<router-link>
: 該標簽是一個vue-router中已經內置的組件, 它會被渲染成一個<a>
標簽. -
<router-view>
: 該標簽會根據當前的路徑, 動態渲染出不同的組件. -
網頁的其他內容, 比如頂部的標題/導航, 或者底部的一些版權信息等會和
<router-view>
處於同一個等級. -
在路由切換時, 切換的是
<router-view>
掛載的組件, 其他內容不會發生改變.
路由的默認路徑
我們這里還有一個不太好的實現:
默認情況下, 進入網站的首頁, 我們希望<router-view>
渲染首頁的內容.
但是我們的實現中, 默認沒有顯示首頁組件, 必須讓用戶點擊才可以.
如何可以讓路徑默認跳到到首頁, 並且<router-view>
渲染首頁組件呢?
非常簡單, 我們只需要配置多配置一個映射就可以了.
配置解析:
我們在routes
中又配置了一個映射.
path
配置的是根路徑: /
redirect
是重定向, 也就是我們將根路徑重定向到/home
的路徑下, 這樣就可以得到我們想要的結果了.
HTML5的History模式
我們前面說過改變路徑的方式有兩種:
-
URL的hash
-
HTML5的history
默認情況下, 路徑的改變使用的URL的hash.
如果希望使用HTML5的history模式, 非常簡單, 進行如下配置即可:
router-link補充
在前面的<router-link>
中, 我們只是使用了一個屬性: to
, 用於指定跳轉的路徑.
<router-link>
還有一些其他屬性:
-
tag
:tag
可以指定<router-link>
之后渲染成什么組件, 比如上面的代碼會被渲染成一個<li>
元素, 而不是<a>
-
replace
:replace
不會留下history
記錄, 所以指定replace
的情況下, 后退鍵返回不能返回到上一個頁面中 -
active-class
: 當<router-link>
對應的路由匹配成功時, 會自動給當前元素設置一個router-link-active
的class
, 設置active-class
可以修改默認的名稱.
在進行高亮顯示的導航菜單或者底部tabbar
時, 會使用到該類.
但是通常不會修改類的屬性, 會直接使用默認的router-link-active
即可.
修改linkActiveClass
該class
具體的名稱也可以通過router
實例的屬性進行修改
exact-active-class
類似於
active-class,
只是在精准匹配下才會出現的class.后面看到嵌套路由時, 我們再看下這個屬性.
路由代碼跳轉
有時候, 頁面的跳轉可能需要執行對應的JavaScript代碼, 這個時候, 就可以使用第二種跳轉方式了
this.$router.push('/home')
比如, 我們將代碼修改如下:
動態路由
在某些情況下,一個頁面的path路徑可能是不確定的,比如我們進入用戶界面時,希望是如下的路徑:
/user/aaaa或/user/bbbb
除了有前面的/user之外,后面還跟上了用戶的ID
這種path和Component的匹配關系,我們稱之為動態路由(也是路由傳遞數據的一種方式)。
1、路由配置
2、在App.vue文件中動態拼接用戶ID(v-bind: 動態綁定 簡寫 :)
3、User.vue文件中顯示獲取的userId
注意$route和$router
這里的$router相當於創建的router實例(即調用router實例里面的方法)
這里的$route是獲取當前活躍的路由
路由懶加載
官方解釋:
當打包構建應用時,Javascript 包會變得非常大,影響頁面加載。
如果我們能把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件,這樣就更加高效了
官方在說什么呢?
首先, 我們知道路由中通常會定義很多不同的頁面.
這個頁面最后被打包在哪里呢? 一般情況下, 是放在一個js文件中.
但是, 頁面這么多放在一個js文件中, 必然會造成這個頁面非常的大.
如果我們一次性從服務器請求下來這個頁面, 可能需要花費一定的時間, 甚至用戶的電腦上還出現了短暫空白的情況.
如何避免這種情況呢? 使用路由懶加載就可以了.
路由懶加載做了什么?
路由懶加載的主要作用就是將路由對應的組件打包成一個個的js代碼塊.
只有在這個路由被訪問到的時候, 才加載對應的組件
懶加載的方式
方式一: 結合Vue的異步組件和Webpack的代碼分析.
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
方式二: AMD寫法
const About = resolve => require(['../components/About.vue'], resolve);
方式三: 在ES6中, 我們可以有更加簡單的寫法來組織Vue異步組件和Webpack的代碼分割.
const Home = () => import('../components/Home.vue')
推薦使用第三種方式
嵌套路由
嵌套路由是一個很常見的功能
比如在home頁面中, 我們希望通過/home/news和/home/message訪問一些內容.
一個路徑映射一個組件, 訪問這兩個路徑也會分別渲染兩個組件.
路徑和組件的關系如下:
實現嵌套路由有兩個步驟:
創建對應的子組件, 並且在路由映射中配置對應的子路由.
在組件內部使用
嵌套路由實現
1、定義兩個組件
2、導入組件和定義路由
3、使用路由
**嵌套路由也可以配置默認的路徑, 配置方式如下: **
傳遞參數
第一步: 創建新的組件Profile.vue
第二步: 配置路由映射
第三步: 添加跳轉的<router-link>
傳遞參數的方式
URL解析:
協議://主機:端口/路徑?查詢
scheme://host:port/path?query#fragment
fragment是指片段的意思
例:
傳遞參數主要有兩種類型: params和query
params的類型:
-
配置路由格式: /router/:id
-
傳遞的方式: 在path后面跟上對應的值
-
傳遞后形成的路徑: /router/123, /router/abc
query的類型:
-
配置路由格式: /router, 也就是普通配置
-
傳遞的方式: 對象中使用query的key作為傳遞方式
-
傳遞后形成的路徑: /router?id=123, /router?id=abc
如何使用它們呢? 也有兩種方式:
router-link
JavaScript代碼
獲取參數
$route和$router****是有區別的
打印$router
打印$route(顯示的是當前活躍的路由)
導航守衛
我們來考慮一個需求: 在一個SPA應用中, 如何改變網頁的標題呢?
網頁標題是通過<title>
來顯示的, 但是SPA
只有一個固定的HTML
, 切換不同的頁面時, 標題並不會改變.
但是我們可以通過JavaScript
來修改<title>
的內容.window.document.title = '新的標題'.
那么在Vue項目中, 在哪里修改? 什么時候修改比較合適呢?
普通的修改方式:
我們比較容易想到的修改標題的位置是每一個路由對應的組件.vue文件中.
通過mounted
聲明周期函數, 執行對應的代碼進行修改即可.
但是當頁面比較多時, 這種方式不容易維護(因為需要在多個頁面執行類似的代碼).
有沒有更好的辦法呢? 使用導航守衛即可.
什么是導航守衛?
vue-router
提供的導航守衛主要用來監聽監聽路由的進入和離開的.
vue-router
提供了beforeEach
和afterEach
的鈎子函數, 它們會在路由即將改變前和改變后觸發.
導航守衛使用
我們可以利用beforeEach
來完成標題的修改.
首先, 我們可以在鈎子當中定義一些標題, 可以利用meta
來定義
其次, 利用導航守衛,修改我們的標題.
導航鈎子的三個參數解析:
-
to
: 即將要進入的目標的路由對象. -
from
: 當前導航即將要離開的路由對象. -
next
: 調用該方法后, 才能進入下一個鈎子.(必須要有)
導航守衛補充
補充一:如果是后置鈎子, 也就是afterEach
, 不需要主動調用next()函數.
補充二: 上面我們使用的導航守衛, 被稱之為全局守衛.
路由獨享的守衛.
組件內的守衛.
更多內容, 可以查看官網進行學習:
keep-alive
keep-alive
是 Vue 內置的一個組件,可以使被包含的組件保留狀態,或避免重新渲染。
它們有兩個非常重要的屬性:
-
include
- 字符串或正則表達,只有匹配的組件會被緩存 -
exclude
- 字符串或正則表達式,任何匹配的組件都不會被緩存<keep-alive exclude="Profile,User"></keep-alive>
router-view
也是一個組件,如果直接被包在 keep-alive 里面,所有路徑匹配到的視圖組件都會被緩存:
通過create
聲明周期函數來驗證
為了實現一個能保留上一個頁面記錄的效果
<script>
export default {
data () {
return {
//固定一個初始路徑
path:'/home/news'
}
},
name:'Home',
//生命周期函數,一旦組件被調用就會調用此函數
created() {
console.log('home created');
},
//生命周期函數,一旦路由改變,上一個組件就會被摧毀
destroyed() {
console.log('home destoryed');
},
//生命周期函數,活躍,調用某個組件,則此組件活躍
activated() {
this.$router.push(this.path);
console.log('activated');
},
deactivated() {
console.log('deactivated');
},
// 組件內的守衛
//beforeRouteLeave(to, from, next) {
// 導航離開該組件的對應路由時調用
// 可以訪問組件實例 `this`
// }
beforeRouteLeave(to,from,next) {
console.log(this.$route.path);
this.path=this.$route.path;
next()
}
}
</script>
小案例(TabBar):
實現思路:
如果在下方有一個單獨的TabBar
組件,你如何封裝
自定義TabBar
組件,在APP中使用
讓TabBar
出於底部,並且設置相關的樣式
2.TabBar
中顯示的內容由外界決定
定義插槽
flex
布局平分TabBar
3.自定義TabBarItem
,可以傳入 圖片和文字
定義TabBarItem
,並且定義兩個(具名)插槽:圖片、文字。
給兩個插槽外層包裝div,用於設置樣式。(防止樣式被替換掉)
填充插槽,實現底部TabBar的效果
.傳入 高亮圖片
定義另外一個插槽,插入active-icon的數據
定義一個變量isActive,通過v-show來決定是否顯示對應的icon
5.TabBarItem綁定路由數據
安裝路由:npm install vue-router —save
完成router/index.js的內容,以及創建對應的組件
main.js中注冊router
APP中加入<router-view>
組件
6.點擊item跳轉到對應路由,並且動態決定isActive
監聽item的點擊,通過this.$router.replace()
替換路由路徑
通過this.$route.path.indexOf(this.link) !== -1
來判斷是否是active
7.動態計算active
樣式
封裝新的計算屬性:this.isActive ? {'color': 'red'} : {}
小技巧(給路徑起別名)
在webpack.base.conf.js
里
在src中使用別名時要加上~