前端框架Vue自學之Vue router(六)


終極目標:掌握和使用Vue(全家桶:Core+Vue-router+Vuex)

本博客目的:記錄Vue學習的進度和心得(Vue router)

內容:學習和使用Vue router。

正文:

Vue router

一、認識路由

  1、路由(routing)就是通過互聯的網絡把信息從源地址傳輸到目的地址的活動。

  2、路由器提供了兩種機制:路由轉送。路由是決定數據包從來源到目的地的路徑。轉送將輸入端的數據轉移到合適的輸出端。

  3、路由中有一個非常重要的概念叫路由表。路由表本質上就是一個映射表,決定了數據包的指向。

二、前端渲染后端渲染和前端路由后端路由

  1、后端渲染和后端路由

  以前的網頁開發整個HTML頁面是由服務器來渲染的,即后端渲染,通過使用JSP(Java server page)/PHP/ASP語言開發的。以JSP為例,當我們在瀏覽器輸入一個網址(url)時,把瀏覽器會發這個網址(url)給服務器,服務器首先會解析這個網頁,在后台就會通過JSP技術(Controller)把網頁寫好,這個網頁包含HTML和CSS和一些Java代碼,Java代碼的作用是從數據庫中讀取數據,並且將它動態地放在頁面中(把數據動態渲染這個頁面)。最后服務器直接將渲染好的網頁發送給瀏覽器(這個網頁只有HTML+CSS)(完成了一個IO操作)。這就是后端渲染(網頁是在服務器端渲染的)。

  可以發現,在后端渲染這種模式下,我們每輸入一次url,服務器就會根據這個url在后端渲染網頁,然后傳到瀏覽器中。一個url(路徑)對應(映射)一個網頁,這個映射關系是服務器管理的。因此后端處理URL和頁面之間的映射關系叫做后端路由

  優點:這種情況下渲染好的頁面,不需要單獨加載任何的JS和CSS,可以直接交給瀏覽器展示,這樣也有利於SEO(搜索引擎優化)的優化。

  缺點:整個頁面的模塊由后端人員來編寫和維護(例如Java數據庫)。前端開發人員如果要開發頁面,需要通過PHP和Java等語言來編寫頁面代碼。而且通常情況下HTML代碼和數據以及對於的邏輯會混在一起,編寫和維護都是非常糟糕的事情。

  2、前后端分離和前端渲染

  網頁開發的第二個階段是前后端分離階段。隨着Ajax(異步 JavaScript 和 XML)的出現,有了前后端分離的開發模式。后端只提供API來返回數據,前端通過Ajax獲取數據,並且可以通過JavaScript將數據渲染到頁面中。

  其過程大致是這樣:后端是一個服務器(提供API接口的服務),服務器連接數據庫;前端在瀏覽器開發;中間還有一個靜態資源服務器(當然有的公司會把后端服務器和靜態資源服務器合在一起)。當我們在瀏覽器輸入網站(url),接着會從靜態資源服務器獲取HTML+CSS+JS代碼等靜態資源,HTML+CSS是可以在瀏覽器直接渲染,JS代碼時由瀏覽器執行,一般JS里面會有API請求,通過Ajax技術,然后向后端服務器請求數據,后端服務器將對於的數據返回給瀏覽器,這些數據會通過其他的JS代碼,在瀏覽器創建HTML元素,並把數據插入其中,最后在渲染整個頁面。

  瀏覽器中顯示的網頁中的大部分內容,都是由前端寫的JS代碼在瀏覽器中執行,最終渲染出來的網頁。這就是前端渲染

  這樣做最大的優點就是前后端責任的清晰,后端專注於數據上,前端專注於交互和可視化上。並且當移動到(IOS、Android)出現后,后端不需要進行任何處理,依然使用之前的一套API即可(因為用的是API接口,不管是瀏覽器,還是移動端,接口對應上即可使用相關服務)。目前很多的網站依然采用這種模式開發。

  3、前端路由

  網頁開發的第三個階段是單頁面富應用SPA(Single Page Application)階段。其實SPA最主要的特點就是在前后端分離的基礎上加上一層前端路由,也就是前端來維護一套路由規則。

  SPA,整個網頁只有一個HTML頁面。之前在前后端分離的時候,靜態資源服務器是一個網址(url)對應一套HTML+CSS+JS,而在SPA中, 靜態資源服務器只有一套index.html+css+JS。即在SPA中,在瀏覽器輸入網頁時,瀏覽器先從靜態服務器獲取HTML+CSS+JS(全部資源)但並非直接執行。但我們點擊這個網址(相當於打開另一url),然后會從HTML+CSS+JS(全部資源)中抽離要在這個url顯示的東西。這時,不同的url中,通過在同一套HTML+CSS+JS(全部資源)中進行抽離,可以顯示不同url對應的頁面信息,這種映射關系就是前端路由。(之前不同的url會向靜態資源服務器請求一套HTML+CSS+JS資源,前端路由不會向靜態資源服務器請求,而是通過一些JS代碼判斷,將從同一套HTML+CSS+JS(全部資源)中抽取一部分資源,其實在vue中就是一個個組件,然后在對應不同的url的頁面中渲染顯示)

  即前端路由就是從不同url在同一套HTML+CSS+JS(全部資源)所對應的不同組件(頁面)資源的映射關系,這個關系是前端在管理的。  

  4、url的hash和HTML5的history

  前端路由的核心是改變url,但是頁面不進行整體的刷新。那怎么做到呢?一個是使用url的hash,一個是使用HTML5的history(的很多模式)。

  url的hash,也就是錨點(#),本質上是改變window.location的href屬性。我們可以直接通過直接賦值location.hash來改變herf,但是頁面不發生刷新。

  為了演示改變url,卻不讓頁面整體刷新,我們先用vue CLI2創建工程,然后記得選擇安裝vue-router。然后運行調試(npm run dev),打開頁面和控制台,發現一開始會加載一些資源(為了方便看是否刷新,可以將Network的clear按鈕點擊(紅色圓旁邊那個禁止圖標))。

    當在控制台Console中通過url的hash修改url時(location.hash = 'aaa'),發現頁面沒有刷新。

(url修改前)

 (修改url的hash)

 (修改url后)

 (network沒有請求資源)

    此外,HTML5的history模式:pushState 也可以修改url卻不刷新網頁。

  (在console通過history修改url)

   (修改了url,但network沒有請求資源,即頁面沒刷新)

   注意history.pushState是一個棧結構(后進先出)。修改的url顯示的是最新push進去的修改項(棧頂)。

   (壓入新url)(顯示棧頂)

   對應的彈出棧頂方法是history.back(),同樣也是修改了url卻不刷新頁面。可以發現此時用這兩種方法是可以在瀏覽器的返回/前進按鈕(一般是瀏覽器左上角的兩個箭頭按鈕)是可以使用的(因為是棧)。history.back()相當於返回,而histor.forward()相當於前進。(注意,url中出現了#,即hash模式,是因為我們之前項目的代碼中,默認的路由實例模式是hash模式,如果修改為history的mode就不會出現#,后面會說第三章第5小節有講)

  (彈出)(顯示棧頂)

   HTML5的history模式:replaceState。同樣可以修改url卻不刷新頁面,但沒有返回按鈕可以使用(因為是代替)。

  (用法)(修改了url,沒刷新頁面,但沒有返回按鈕可以使用)

   HTML5的history模式:go。history.back()相當於history.go(-1),而histor.forward()相當於history.go(1)。go里面的參數可以是-2 等,相當於執行history.back()兩次。上述三個方法等同於瀏覽器的前進后退。

  總結:以后在配置路由時,就有兩種方式:hash方式和history方式。   

三、Vue-router

  1、前端框架的前端路由

  目前前端流行的三大框架,都有自己的路由實現。如Angular的ngRouter,React的ReactRouter,Vue的Vue-router。

  2、認識vue-router

  vue-router是vue.js官方的路由插件,它和vue.js是深度集成的,適合用於構建單頁面應用。

  vue-router是基於路由和組件的。路由用於設定訪問路徑,將路徑和組件映射起來。在vue-router的單頁面應用中,頁面的路徑的改變就是組件的切換。

  3、vue-router的安裝和使用

  因為之前我們學習了webpack(在我前一個博客),后續開發中我們主要是通過工程化的方式進行開發的。所有在后續,我們直接使用npm來安裝路由即可。

  步驟一:安裝vue-router(npm install vue-router --save)(運行時依賴)。如果是之前通過vueCLI創建項目的時候,選擇安裝的了vue-router,可以在package.json文件可以看到vue-router,並且在src會自動創建router文件夾和一個關於路由的index.js(下面也會講到手動安裝和時候vue-router,不慌)。

  

    步驟二:在模塊化工程中使用它(因為是一個插件,所以可以通過vue.use()來安裝路由功能)。首先,導入路由對象,並且調用Vue.use(VueRouter)。接着,創建路由實例,並且傳入路由映射配置。最后,在vue實例中掛載創建的路由實例。

  如果我們通過vueCLI創建項目的時候,沒有選擇安裝vue-router,也可以手動安裝上面兩個步驟安裝使用。

  大致流程:安裝vue-router。終端輸入npm install vue-router --save。使用vue-router。首先,在src文件夾下創建名為router的文件夾,用來放置我們路由配置的相關信息。接着,在router文件夾下創建index.js文件,配置路由信息,其中,導入VueRouter,調用Vue.use()方法安裝VueRouter插件,由於這個是vue方法,需要導入vue,接着,創建VueRouter對象,並在這個對象中傳入路由映射配置,並將其導出,供vue實例掛載。

  (router文件夾下的index.js)

    最后一步是在main.js里面導入router,並在vue實例掛載。這樣就可以使用router了。

  (main.js)

    4、路由映射配置和呈現出來

   使用vue-router的步驟:首先,創建路由組件。接着,配置路由映射:組件和路徑映射關系。最后,使用路由:通過<router-link>和<router-view>。

  大致操作過程:

  第一步,在src文件夾下,創建組件,例如創建兩個組件About.vue和Home.vue。

  (About.vue)(Home.vue)

   第二步,然后在router的index.js文件進行映射配置,一個映射是一個對象,對象中包含兩個屬性:path和component(這樣就把路徑和組件對應起來了),接着導入組件,把組件放置在映射對象的component屬性中,所以這里我們配置兩個對象。注意,path是相對路徑,而不是url(url是協議頭://host/query等)。

  (router文件夾的index.js文件)

   第三步,接着,使用路由。由於需要在同一個頁面想顯示兩個不同路徑下兩個組件。所以我們得從App.vue修改(因為入口文件main.js導入的是App.vue,並將其用render函數渲染顯示出來),添加兩個標簽按鈕,通過按鈕進行修改路徑。所以,我們在App.vue的template標簽內使用<router-link>標簽(router-link是vue-route已經r注冊的全局組件),並且<router-link>標簽里面有個to屬性,將to屬性的屬性值對應於我們之前映射關系的相對路徑path,這樣就可以和相對路徑path的組件對應。(<router-link>標簽最終渲染為<a>標簽)

  但此時只使用<router-link>標簽只能修改url,而對應地址所映射的組件沒有顯示出來,此時,需要使用<router-view>標簽。但注意,<router-view>所顯示的組件的位置是可以調的,后續我們會學習如果讓他在我們想要的位置上(利用框架),此外在路由切換時,切換的是<router-view>掛載的組件,其他內容是不會發生改變的。

  (App.vue,<router-view>的位置會絕對組件顯示的位置,例如組件顯示在兩個<router-link>標簽的下面)

   (此時點擊首頁對應的home相對路徑了;點擊關於對應about相對路徑)

  5、路由的默認值和修改為history模式

  之前在默認情況下,進入網站的首頁,我們希望<router-view>渲染首頁的內容,但是在我們之前的實現中, 默認沒有顯示首頁組件,必須要讓用戶點擊才可以。

  如何可以讓路徑默認跳到首頁,並且<router-view>渲染首頁組件呢?非常簡單,我們只需要在路由配置多配置一個映射就可以了,即在routers多配置一個映射,path配置的是根路徑:/或者為空,redirect是重定向,也就是我們將根路徑重定向到/home的路徑下,這樣就可以得到我們想要的結果了。

  (index.js添加重定向)

   (沒有點擊首頁,直接打開就是默認為首頁,並渲染了組件)

   在之前修改url的時候發現都是相對路徑前面帶有#,即是hash值模式(路由默認下是hash模式)。如果我們不想要這個#,可以使用HTML5的history。

  我們在index.js中在VueRouter實例中,添加mode屬性,並且值為history即可。

  (index.js中的VueRouter實例) 

(相對路徑/home前面沒有了#)

   6、<router-link>的其他屬性補充。

  之前我們只使用了<router-link>的to屬性,即點擊這個link跳轉到對應的相對路徑。

  <router-link>還有一些其他屬性:

  tag:tag可以指定<router-link>之后渲染成什么組件,比如之前寫的<router-link>默認渲染為<a>,通過tag我們可以渲染為<button>等(<router-link to ='/home' tag='button'>首頁</router-link>)。

  replace:replace不會留下history記錄,所以指定replace的情況下,后退鍵返回不能返回到上一個頁面中(之前用的相當於是history.pushState,所以后退鍵可以使用)。用法:不需要寫任何值,就replace即可(<router-link to ='/home' tag='button' replace >首頁 </router-link>)。

  active-class:當<router-link>對應的路由匹配成功時,會自動給當前元素設置一個router-link-active的class,設置active-class可以修改默認的名稱。或者是直接在router文件夾的index.js文件中的VueRouter實例中,使用linkActiveClass屬性進行統一修改router-link-active的名稱。在進行高亮顯示的導航菜單或者底部tabbar時,會使用到該類,但是通常不會修改類的屬性,會直接使用默認的router-link-active即可。

  7、通過代碼跳轉路由

  如果我們想在別的標簽,擁有使用<router-link>的跳轉功能,可以通過代碼的方式跳轉路由。

  例如,通過事件監聽,定義方法和使用$router,獲取router對象(這個router對象就是我們定義的VueRouter實例)的方式。在App.vue中創建兩個button,並且監聽事件,然后在腳本定義方法。this.$router相當於vue-router對象,其屬性可以選為push(相當於history.pushState)或replace(相當於history.replaceState),但注意不能直接使用history方法,這樣繞過了router了。

 

   8、vue-router的動態路由使用

  在某些情況下,一個頁面的path路徑可能是不確定的,比如我們進入用戶界面時,希望如下的路徑:/user/aaa或/user/bbb,除了有前面的/user之外,后面還跟上了用戶的ID。這種path和component的匹配關系,我們稱之為動態路由(也是路由傳遞數據的一種方式)。

  例如我們要創建用戶的一些動態路由(例如/user路徑后面能跟上一些用戶的id的路徑)。

  實例大致過程:第一,先創建/user的路徑。首先,在src/components下創建User.vue(組件),然后在/router下的index.js進行配置User路由對象(User相對路徑和組件對象關系),最后是在App.vue用使用<router-link>和<router-view>引用User組件。這樣就完成了/user的路由【第一大步驟之前在第4小節說過】

  現在我們要想使用動態路由(例如/user路徑后面能跟上一些用戶的id的路徑)。

  假如我們想動態從腳本中的data數據獲取userId(一個變量)。例如zhangsan。

  (App.vue) 

   首先,修改index.js中的user組件配置。(:/變量名)

  (修改前)(修改后)

   接着在<router-link>中用v-bind:綁定to屬性即可,往對應變量userID傳data里面的值。

  

   此時,點擊用戶,url就可以動態變為user/userId,即user/zhangsan。

  (點擊用戶)

  進一步地,如果我們想根據userId,如zhangsan,獲取他的一些信息,渲染到當前頁面(而不是之前默認的user組件的原來的信息:我們是用戶界面 我是用戶的相關信息)。

  我們可以使用$route(之前我們講過$router是我們之前創建VueRouter實例對象,而這個是$route,是指的是VueRouter實例對象的routers(里面有很多個路由對象)中處於活躍active的對應的路由對象)。並且在User.vue組件中使用計算屬性。

  (user.vue)

  此時,打開頁面,點擊用戶。url后面有user/userId,<router-view>中的h2標簽中的userId也被渲染出來了。

  (點擊用戶)

   同樣地,此時如果App.vue中的data的userId改變了,變為lisi。最后頁面的userId也會相應變化。

(App.vue)

  (userId為lisi)

  這就是動態路由。

  9、打包文件的解析

  路由的懶加載。當打包構建應用時,JavaScript包會變得非常大,影響頁面加載(由於請求的資源過大,會在頁面有暫時空白顯示)。如果我們把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件,這樣就更加高效了。

  在我們用vue CLI構建項目的時候,當打包的時候,就是把目標文件分為幾個文件(而不是之前的一個bundle.js文件)。其中,js文件夾中,app.XX.js是當前應用程序開發的所有代碼(業務代碼),vendor.XX.js是vendor(提供商,第三方的東西:vue/vue-router/axios(網絡請求框架)/bs(一種滾動框架)),manifest.xx.js是為了打包的代碼做底層支持的(如導入導出,ES6轉ES5等)。

  注意,.map文件是js文件壓縮后,文件的變量名替換對應、變量所在位置等元信息數據文件,一般這種文件和min.js主文件放在同一個目錄下。 這樣的好處就是說,在調試的時候,如果有一些JS報錯,那么瀏覽器會通過解析這個map文件來重新merge壓縮后的js,使開發者可以用未壓縮前的代碼來調試,這樣會給我們帶來很大的方便。

  

   路由懶加載的使用。懶加載,用到時再加載,相當於將路由對應的組件打包成一個個的js代碼塊,只有在這個路由被訪問到的時候,才加載對應的組件。

   路由懶加載的方式有:

  方式一:結合Vue的異步組件和Webpack的代碼分析(不推薦)。const Home= resolve => { require.ensure(['../components/Home.vue'], () =>{ resolve(require('../components/Home.vue')) })};

  方式二:ADM寫法(不推薦)。 const About = resolve => require(['../components/About.vue'], resolve);

  方式三:在ES6中,我們可以有更加簡單的寫法來組織Vue異步組件和Webpack的代碼分割(強推)。const Home = () => import('../components/Home.vue')

   所以,我們重新在之前的路由配置代碼(index.js)使用懶加載。首先,注釋掉組件包的導入,然后用方式三的路由懶加載,然后在配置常亮routes中對應組件放置對應模塊。

  (index.js

    此時,打包,可以發現打包的js文件夾內多個幾個.js文件,即不同路由路徑的js代碼塊。因為有三個組件,所以是0 1 2的js文件。

  

   10、路由的嵌套使用

  嵌套路由(在路由里面嵌套另一個路由)是一個很常見的功能。比如在home頁面中,我們希望通過/home/news和/home/message訪問一些內容。一個路徑映射一個組件,訪問這兩個路徑也會分別渲染兩個組件。即路徑和組件的關系如下:

  

  實現嵌套路由有兩個步驟:首先,創建對應的子組件,並且在路由映射中配置對應的子路由。接着,在組件內部使用<router-view>標簽。

  大致操作流程:首先,在src/components下創建子組件HomeNews.vue和HomeMessage.vue。接着,在router下的index.js中,在home組件的映射配置中配置其兩個子組件(這才是嵌套嘛,通過利用children屬性),並且也是使用懶加載。

  

     最后,在Home.vue(父組件)中使用使用組件的方法一樣,使用<router-link>和<router-view>來顯示我們的兩個子組件。注意,<router-link>中的to屬性得寫完整的相對路徑。

  (Home.vue)

    然后,運行調試,發現首頁有了兩個子組件路由,點擊新聞或消息,頁面會渲染其組件(子組件)。

  (home頁面)

   (渲染子組件)

   11、傳遞參數

  有時候我們的使用路由,會把一些參數傳遞過去。(我們之前傳遞userId就屬於一種參數傳遞)

  傳遞參數主要有兩種類型:paramsquery。使用方式:<router-link>的方式和JavaScript代碼方式。

  params的類型:配置路由格式:/router/:id  ;傳遞方式:在path后面跟上對應的值;傳遞后形成的路徑:/router/123,/router/abc 。

  這個例子之前在第8小節有說。(通過$route.params.id)

  query的類型:配置路由格式:/router,也就是普通配置;傳遞方式:對象中使用query的key作為傳遞方式;傳遞后形成的路徑:/router?id=123, /router?id=abc。

  為了演示傳遞參數(query類型),我們這里再創建一個組件,並且將其配置好。首先,創建新的組件Profile.vue;接着,配置路由映射;最后,添加跳轉的<router-link>。

  大致流程:src/components創建Profile.vue組件,接着在router/index.js配置路由(懶加載的方式),然后在App.vue中使用<router-link>。

  (頁面展示沒有問題)

   現在,我們想向Profile傳遞參數。首先我們在router-link中用v-bind綁定to屬性,並使用對象把路由路徑傳入(這是方便我們后續傳遞參數的使用)。

  

   由於to綁定是一個對象,所以里面可以不止一個屬性,我們可以寫入我們的query。

  

   此時的頁面,url路徑把我們的query對象加載了。(注意是問號連接,這就是query方式拼接,查詢)

    

   補充:統一資源定位符的標准格式如下:[協議類型]://[服務器地址]:[端口號]/[資源層級UNIX文件路徑][文件名]?[查詢]#[片段ID],一般是 協議://主機:端口//路徑?查詢(scheme://host:port/path?query#fragment)。

  這個時候,如果我們想取出query對象,並渲染顯示在頁面上可以通過$route.query(在Profile.vue中)。query對象能取出來,對象的屬性也是可以取出來的,如$route.query.name等。

  (使用$route.query)

    (頁面顯示query對象)

   如果我們是想從別的HTML標簽進行類似用組件路由的參數傳遞,可以使用監聽事件和定義方法和this.$router.push或者replace(之前講過啦)。

  (App.vue中)

    (添加方法)

    (頁面展示)

    12、router和route由來

  $router就是創建VueRouter的實例(即我們定義名為router的那個常量,vue-router源碼實現的),通過打開VueRouter(VScode中按Ctrl+鼠標左鍵),發現里面有很多方法,例如push,replace。所以我們可以通過$router對象,使用這些方法(之前就是這么做的)。

  (index.js)

   (點開VueRouter)

  $route是當前處於活躍的路由,即頁面渲染的路由(也是vue-router源碼實現的)。

   補充1:所有的組件都繼承自Vue類的原型

  補充2:之前講過,使用一個plugin即插件,如VueRouter,要先Vue.use(ueRouter),其會執行ueRouter.install。所以如果我們想看VueRouter(vue-router)的源碼,GitHub下載(注意是從node_modules看版本哦),然后打開其install.js開始看。會發現install.js里面有用Vue.component()全局注冊了RouterView和RouterLink組件(也就是我們之前使用的<router-view>,<router-link>)。

   13、全局導航守衛

  當我們在進行路由跳轉的時候,我們想監聽跳轉過程,從而進行一些操作,這就是導航守衛。

  我們來考慮一個需求:在一個SPA應用中,如何改變網頁的標題呢?網頁標題是通過<title>來顯示的,但是SPA只有一個固定的HTML,切換不同的頁面時,標題並不會改變。但是我們可以通過JavaScript來修改<title>的內容,window.document.title='新的標題'。那么在Vue項目中,在哪里修改?什么時候修改比較合適呢?

  利用vue的生命周期函數。create()創建出組件時回調的,mounted()我們的template掛載到整個DOM時回調的,updated()整個界面發生刷新時回調的。

  所以導航守衛可以第一種寫法:把create(){document.title='對應標題'}放入每個跳轉路由的組件內。

  但是這樣寫很累贅,每次有新組件如果需要這個功能,則都要加上,很麻煩。

  可以發現,其本質是路由跳轉,我們只需監聽路由跳轉,當路由跳轉了,就修改對應的document.title即可。這就是全局導航守衛(監聽全局的跳轉)。

  大致流程:首先在router/index.js中,對路由實例使用beforeEach()函數(它會在路由即將改變前觸發(即前置鈎子/前置守衛),對應的還有afterEach()),這個函數看源碼:

  (打開beforeEach())

  (打開NavigationGuard)

  即路由的beforeEach()里面需要一個函數,里面包含三個參數:to,from,next。(其中next方法必須使用,否則無法路由跳轉,因為原來內部beforeEach()是使用next(),當我們使用這個beforeEach()會把原來的beforeEach()覆蓋的)注意,源碼中,to和from都是Route類型,代表着從from跳轉到to。

  所以我們在index.js中的所有路由中加上一個meta元數據對象,里面放置對應的title。(元數據:描述數據的數據)

  (home配置路由中加入meta,其他配置路由也是一樣)

  最后在index.js中,使用beforeEach()方法。

   

   然后當我們點擊首頁時,頁面標題顯示‘首頁’。點擊關於,頁面標題顯示‘關於’

 (點擊 首頁)

   但是,當我們點擊首頁的子組件的時候,發現沒有顯示標題,例如此時我們點擊‘新聞’。

  (點擊‘新聞’,標題是undefined)

  這是因為子組件之前使用了路由嵌套。相當於此時我們獲取的to屬性是不同與父組件的,即沒有meta,所以我們修改為:

document.title = to.matched[0].meta.title; 獲取父組件的meta。此時就可以了。
   (點擊‘新聞’ 顯示title)

   補充1:剛才講的是前置鈎子(beforeEach()),如果是后置鈎子,即afterEach,不需要主動調用next()函數(源碼里也是說不需要的,因為表示的是路由跳轉完了)。

  補充2:前置鈎子/前置守衛 和后置鈎子都稱之為全局守衛。除了全局守衛,還有路由獨享的守衛組件內的守衛。進一步了解可以看官網:VueRouter的導航守衛

  14、vue-router keep-alive及其他問題

  keep-alive是vue內置的一個組件,可以使被包含的組件保留狀態,或避免重新渲染。例如,當我們點擊渲染到某個A組件時,假設A組件里有兩個子組件A1和A2,當點擊A組件默認是先渲染A1時,我們再點擊A2,當然此時渲染到A2。此時如果我們點擊另一個路由,到B組件,再點擊回A組件,此時,A組件中還是先渲染A1而不是我們之前最后操作的A2。原因是點擊A組件時相當於Vue生命周期的creat(),當點擊B組件是,相當於A的生命周期的destroy(),再點擊回A,相當新創建create了A,所以A是回到默認狀態A1,而不是destroy前的狀態A2。如果我們想回到A2,則可以使用keep-alive。

  router-view也是一個組件(之前分析vue-router源碼的時候可見),如果直接被包在keep-alive里面,所有路徑匹配到的視圖組件都會被緩存。

  所以,大致做法是:將原來的<router-view>標簽包含在<keep-alive>標簽內。

  注意,可能行不通,因為路徑關系沒有配置好,需要用到activated()激活函數和beforeRouterLeave的組件內守衛。在離開路由組件時,通過beforeRouterLeave函數把路由棧頂路徑保存為當前路徑,然后activated()每次在激活的頁面前把路徑壓進路由棧,即,保存了每次跳轉路由前的路徑為棧頂。

  (home.vue)

   所以,整個過程是:點擊A,默認打開A1,執行activated(),將A1的路徑壓進棧,點擊A2前一刻,A1要離開了,執行了beforeRouterLeave(),把上一次的路徑(A1路徑)變為當前路徑,因為點擊A2,執行activated(),將上一次A1離開時,A1的路徑壓進棧(即棧頂記錄的是上一次點擊的組件路徑)。當點擊B,棧頂的保存的是A2的路徑。所以當再點擊A時,由於使用了keep-alive,緩存了,所以顯示A2。

  補充1:activated()和deactivated()這兩個函數用於某組件中,在<keep-alive>標簽(保持了狀態)內的這個組件的<router-view>才有效,沒有<keep-alive>包含的話,就不起作用(因為這兩個函數是<keep-alive>的鈎子函數)。

  補充2:keep-alive有兩個重要的屬性:include,字符串或正則表達式,只有匹配的組件會被緩存;exclude,字符串或正則表達式,任何匹配的組件都不會被緩存。注意多個屬性間不用加空格(因為涉及到正則表達規范的問題),如exclude=“Profile,user”不要寫成xclude=“Profile, user”。

 

  vue-router的大致知識就是這些了,下一個博客就是關於vue-router的小案例:Tabbar

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM