Vue中鉤子函數(shù)的示例分析

這篇文章主要介紹了Vue中鉤子函數(shù)的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)建站堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:做網(wǎng)站、網(wǎng)站設(shè)計、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的項城網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

Vue-Router導(dǎo)航守衛(wèi):

有的時候,我們需要通過路由來進行一些操作,比如最常見的登錄權(quán)限驗證,當(dāng)用戶滿足條件時,才讓其進入導(dǎo)航,否則就取消跳轉(zhuǎn),并跳到登錄頁面讓其登錄。

為此我們有很多種方法可以植入路由的導(dǎo)航過程:全局的, 單個路由獨享的, 或者組件級的,推薦優(yōu)先閱讀路由文檔

全局守衛(wèi)

vue-router全局有三個守衛(wèi):

  1. router.beforeEach 全局前置守衛(wèi) 進入路由之前

  2. router.beforeResolve 全局解析守衛(wèi)(2.5.0+) 在beforeRouteEnter調(diào)用之后調(diào)用

  3. router.afterEach 全局后置鉤子 進入路由之后

使用方法:

 // main.js 入口文件
 import router from './router'; // 引入路由
 router.beforeEach((to, from, next) => { 
  next();
 });
 router.beforeResolve((to, from, next) => {
  next();
 });
 router.afterEach((to, from) => {
  console.log('afterEach 全局后置鉤子');
 });

to,from,next 這三個參數(shù):

to和from是將要進入和將要離開的路由對象,路由對象指的是平時通過this.$route獲取到的路由對象。

  1. next:Function 這個參數(shù)是個函數(shù),且必須調(diào)用,否則不能進入路由(頁面空白)。

  2. next() 進入該路由。

  3. next(false): 取消進入路由,url地址重置為from路由地址(也就是將要離開的路由地址)。

  4. next 跳轉(zhuǎn)新路由,當(dāng)前的導(dǎo)航被中斷,重新開始一個新的導(dǎo)航。

我們可以這樣跳轉(zhuǎn):next('path地址')或者next({path:''})或者next({name:''})

且允許設(shè)置諸如 replace: true、name: 'home' 之類的選項

以及你用在router-link或router.push的對象選項。

路由獨享守衛(wèi)

如果你不想全局配置守衛(wèi)的話,你可以為某些路由單獨配置守衛(wèi):

 const router = new VueRouter({
  routes: [
  {
   path: '/foo',
   component: Foo,
   beforeEnter: (to, from, next) => { 
   // 參數(shù)用法什么的都一樣,調(diào)用順序在全局前置守衛(wèi)后面,所以不會被全局守衛(wèi)覆蓋
   // ...
   }
  }
  ]
 })

路由組件內(nèi)的守衛(wèi):

  1. beforeRouteEnter 進入路由前

  2. beforeRouteUpdate (2.2) 路由復(fù)用同一個組件時

  3. beforeRouteLeave 離開當(dāng)前路由時

文檔中的介紹:

 beforeRouteEnter (to, from, next) {
 // 在路由獨享守衛(wèi)后調(diào)用 不!能!獲取組件實例 `this`,組件實例還沒被創(chuàng)建
 },
 beforeRouteUpdate (to, from, next) {
 // 在當(dāng)前路由改變,但是該組件被復(fù)用時調(diào)用 可以訪問組件實例 `this`
 // 舉例來說,對于一個帶有動態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時候,
 // 由于會渲染同樣的 Foo 組件,因此組件實例會被復(fù)用。而這個鉤子就會在這個情況下被調(diào)用。
 },
 beforeRouteLeave (to, from, next) {
 // 導(dǎo)航離開該組件的對應(yīng)路由時調(diào)用,可以訪問組件實例 `this`
 }

beforeRouteEnter訪問this

因為鉤子在組件實例還沒被創(chuàng)建的時候調(diào)用,所以不能獲取組件實例 this,可以通過傳一個回調(diào)給next來訪問組件實例。

但是回調(diào)的執(zhí)行時機在mounted后面,所以在我看來這里對this的訪問意義不太大,可以放在created或者mounted里面。

 beforeRouteEnter (to, from, next) {
 console.log('在路由獨享守衛(wèi)后調(diào)用');
  next(vm => {
  // 通過 `vm` 訪問組件實例`this` 執(zhí)行回調(diào)的時機在mounted后面,
  })
 }

beforeRouteLeave:

導(dǎo)航離開該組件的對應(yīng)路由時調(diào)用,我們用它來禁止用戶離開,比如還未保存草稿,或者在用戶離開前,將setInterval銷毀,防止離開之后,定時器還在調(diào)用。

 beforeRouteLeave (to, from , next) {
  if (文章保存) {
  next(); // 允許離開或者可以跳到別的路由 上面講過了
  } else {
  next(false); // 取消離開
  }
 }

關(guān)于鉤子的一些知識:

路由鉤子函數(shù)的錯誤捕獲

如果我們在全局守衛(wèi)/路由獨享守衛(wèi)/組件路由守衛(wèi)的鉤子函數(shù)中有錯誤,可以這樣捕獲:

 router.onError(callback => { 
 // 2.4.0新增 并不常用,了解一下就可以了 
  console.log(callback, 'callback');
 });

在路由文檔中還有更多的實例方法:動態(tài)添加路由等,有興趣可以了解一下。

跳轉(zhuǎn)死循環(huán),頁面永遠空白

我了解到的,很多人會碰到這個問題,來看一下這段偽代碼:

 router.beforeEach((to, from, next) => {
  if(登錄){
   next()
  }else{
   next({ name: 'login' }); 
  }
 });

看邏輯貌似是對的,但是當(dāng)我們跳轉(zhuǎn)到login之后,因為此時還是未登錄狀態(tài),所以會一直跳轉(zhuǎn)到login然后死循環(huán),頁面一直是空白的,所以:我們需要把判斷條件稍微改一下。

if(登錄 || to.name === 'login'){ next() } 
// 登錄,或者將要前往login頁面的時候,就允許進入路由

全局后置鉤子的跳轉(zhuǎn):

文檔中提到因為router.afterEach不接受next函數(shù)所以也不會改變導(dǎo)航本身,意思就是只能當(dāng)成一個鉤子來使用,但是我自己在試的時候發(fā)現(xiàn),我們可以通過這種形式來實現(xiàn)跳轉(zhuǎn):

 // main.js 入口文件
 import router from './router'; // 引入路由
 router.afterEach((to, from) => {
  if (未登錄 && to.name !== 'login') {
  router.push({ name: 'login' }); // 跳轉(zhuǎn)login
  }
 });

額,通過router.beforeEach 也完全可以實現(xiàn)且更好,我就騷一下。

完整的路由導(dǎo)航解析流程(不包括其他生命周期):

  1. 觸發(fā)進入其他路由。

  2. 調(diào)用要離開路由的組件守衛(wèi)beforeRouteLeave

  3. 調(diào)用局前置守衛(wèi):beforeEach

  4. 在重用的組件里調(diào)用 beforeRouteUpdate

  5. 調(diào)用路由獨享守衛(wèi) beforeEnter。

  6. 解析異步路由組件。

  7. 在將要進入的路由組件中調(diào)用beforeRouteEnter

  8. 調(diào)用全局解析守衛(wèi) beforeResolve

  9. 導(dǎo)航被確認。

  10. 調(diào)用全局后置鉤子的 afterEach 鉤子。

  11. 觸發(fā)DOM更新(mounted)。

  12. 執(zhí)行beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)

你不知道的keep-alive[我猜你不知道]

在開發(fā)Vue項目的時候,大部分組件是沒必要多次渲染的,所以Vue提供了一個內(nèi)置組件keep-alive來緩存組件內(nèi)部狀態(tài),避免重新渲染,文檔在這里。

文檔:和 <transition>相似,<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現(xiàn)在父組件鏈中。

用法:

緩存動態(tài)組件:

<keep-alive>包裹動態(tài)組件時,會緩存不活動的組件實例,而不是銷毀它們,此種方式并無太大的實用意義。
 <!-- 基本 -->
 <keep-alive>
  <component :is="view"></component>
 </keep-alive>
 
 <!-- 多個條件判斷的子組件 -->
 <keep-alive>
  <comp-a v-if="a > 1"></comp-a>
  <comp-b v-else></comp-b>
 </keep-alive>

緩存路由組件:

使用keep-alive可以將所有路徑匹配到的路由組件都緩存起來,包括路由組件里面的組件,keep-alive大多數(shù)使用場景就是這種。

 <keep-alive>
  <router-view></router-view>
 </keep-alive>

生命周期鉤子:

這篇既然是Vue鉤子函數(shù)的專場,那肯定要扣題呀~

在被keep-alive包含的組件/路由中,會多出兩個生命周期的鉤子:activated deactivated。

文檔:在 2.2.0 及其更高版本中,activated 和 deactivated 將會在  樹內(nèi)的所有嵌套組件中觸發(fā)。

activated在組件第一次渲染時會被調(diào)用,之后在每次緩存組件被激活時調(diào)用。

activated調(diào)用時機:

第一次進入緩存路由/組件,在mounted后面,beforeRouteEnter守衛(wèi)傳給 next 的回調(diào)函數(shù)之前調(diào)用:

beforeMount=> 如果你是從別的路由/組件進來(組件銷毀destroyed/或離開緩存deactivated)=>mounted=> activated 進入緩存組件 => 執(zhí)行 beforeRouteEnter回調(diào)

因為組件被緩存了,再次進入緩存路由/組件時,不會觸發(fā)這些鉤子:

// beforeCreate created beforeMount mounted 都不會觸發(fā)。

所以之后的調(diào)用時機是:

組件銷毀destroyed/或離開緩存deactivated => activated 進入當(dāng)前緩存組件 => 執(zhí)行 beforeRouteEnter回調(diào)

  // 組件緩存或銷毀,嵌套組件的銷毀和緩存也在這里觸發(fā)

deactivated:組件被停用(離開路由)時調(diào)用

使用了keep-alive就不會調(diào)用beforeDestroy(組件銷毀前鉤子)和destroyed(組件銷毀),因為組件沒被銷毀,被緩存起來了。

這個鉤子可以看作beforeDestroy的替代,如果你緩存了組件,要在組件銷毀的的時候做一些事情,你可以放在這個鉤子里。

如果你離開了路由,會依次觸發(fā):

組件內(nèi)的離開當(dāng)前路由鉤子beforeRouteLeave =>  路由前置守衛(wèi) beforeEach =>全局后置鉤子afterEach => deactivated 離開緩存組件 => activated 進入緩存組件(如果你進入的也是緩存路由)

如果離開的組件沒有緩存的話 beforeDestroy會替換deactivated 

如果進入的路由也沒有緩存的話  全局后置鉤子afterEach=>銷毀 destroyed=> beforeCreate等

那么,如果我只是想緩存其中幾個路由/組件,那該怎么做?

緩存你想緩存的路由:

Vue2.1.0之前:

想實現(xiàn)類似的操作,你可以:

  1. 配置一下路由元信息

  2. 創(chuàng)建兩個keep-alive標(biāo)簽

  3. 使用v-if通過路由元信息判斷緩存哪些路由。

<keep-alive>
  <router-view v-if="$route.meta.keepAlive">
   <!--這里是會被緩存的路由-->
  </router-view>
 </keep-alive>
 <router-view v-if="!$route.meta.keepAlive">
  <!--因為用的是v-if 所以下面還要創(chuàng)建一個未緩存的路由視圖出口-->
 </router-view>
 //router配置
 new Router({
 routes: [
  {
  path: '/',
  name: 'home',
  component: Home,
  meta: {
   keepAlive: true // 需要被緩存
  }
  },
  {
  path: '/:id',
  name: 'edit',
  component: Edit,
  meta: {
   keepAlive: false // 不需要被緩存
  }
  }
 ]
 });

Vue2.1.0版本之后:

使用路由元信息的方式,要多創(chuàng)建一個router-view標(biāo)簽,并且每個路由都要配置一個元信息,是可以實現(xiàn)我們想要的效果,但是過于繁瑣了點。

幸運的是在Vue2.1.0之后,Vue新增了兩個屬性配合keep-alive來有條件地緩存 路由/組件。

新增屬性:

  • include:匹配的 路由/組件 會被緩存

  • exclude:匹配的 路由/組件 不會被緩存

includeexclude支持三種方式來有條件的緩存路由:采用逗號分隔的字符串形式,正則形式,數(shù)組形式。

正則和數(shù)組形式,必須采用v-bind形式來使用。

緩存組件的使用方式:

 <!-- 逗號分隔字符串 -->
 <keep-alive include="a,b">
  <component :is="view"></component>
 </keep-alive>
 
 <!-- 正則表達式 (使用 `v-bind`) -->
 <keep-alive :include="/a|b/">
  <component :is="view"></component>
 </keep-alive>
 
 <!-- 數(shù)組 (使用 `v-bind`) -->
 <keep-alive :include="['a', 'b']">
  <component :is="view"></component>
 </keep-alive>

但更多場景中,我們會使用keep-alive來緩存路由:

<keep-alive include='a'>
 <router-view></router-view>
</keep-alive>

匹配規(guī)則:

1、首先匹配組件的name選項,如果name選項不可用。

2、則匹配它的局部注冊名稱。 (父組件 components 選項的鍵值)

3、匿名組件,不可匹配。

比如路由組件沒有name選項,并且沒有注冊的組件名。

4、只能匹配當(dāng)前被包裹的組件,不能匹配更下面嵌套的子組件。

比如用在路由上,只能匹配路由組件的name選項,不能匹配路由組件里面的嵌套組件的name選項。

5、文檔:<keep-alive>不會在函數(shù)式組件中正常工作,因為它們沒有緩存實例。

6、exclude的優(yōu)先級大于include

也就是說:當(dāng)include和exclude同時存在時,exclude生效,include不生效。

 <keep-alive include="a,b" exclude="a">
 <!--只有a不被緩存-->
 <router-view></router-view>
 </keep-alive>

當(dāng)組件被exclude匹配,該組件將不會被緩存,不會調(diào)用activated 和 deactivated。

組件生命周期鉤子:

關(guān)于組件的生命周期,是時候放出這張圖片了:

Vue中鉤子函數(shù)的示例分析

這張圖片已經(jīng)講得很清楚了,很多人這部分也很清楚了,大部分生命周期并不會用到,這里提一下幾點:

  1. ajax請求最好放在created里面,因為此時已經(jīng)可以訪問this了,請求到數(shù)據(jù)就可以直接放在data里面。這里也碰到過幾次,面試官問:ajax請求應(yīng)該放在哪個生命周期。

  2. 關(guān)于dom的操作要放在mounted里面,在mounted前面訪問dom會是undefined。

  3. 每次進入/離開組件都要做一些事情,用什么鉤子:

不緩存:

進入的時候可以用created和mounted鉤子,離開的時候用beforeDestory和destroyed鉤子,beforeDestory可以訪問this,destroyed不可以訪問this。

緩存了組件:

緩存了組件之后,再次進入組件不會觸發(fā)beforeCreate、created 、beforeMount、 mounted,如果你想每次進入組件都做一些事情的話,你可以放在activated進入緩存組件的鉤子中。

同理:離開緩存組件的時候,beforeDestroy和destroyed并不會觸發(fā),可以使用deactivated離開緩存組件的鉤子來代替。

觸發(fā)鉤子的完整順序:

將路由導(dǎo)航、keep-alive、和組件生命周期鉤子結(jié)合起來的,觸發(fā)順序,假設(shè)是從a組件離開,第一次進入b組件:

  1. beforeRouteLeave:路由組件的組件離開路由前鉤子,可取消路由離開。

  2. beforeEach: 路由全局前置守衛(wèi),可用于登錄驗證、全局路由loading等。

  3. beforeEnter: 路由獨享守衛(wèi)

  4. beforeRouteEnter: 路由組件的組件進入路由前鉤子。

  5. beforeResolve:路由全局解析守衛(wèi)

  6. afterEach:路由全局后置鉤子

  7. beforeCreate:組件生命周期,不能訪問this。

  8. created:組件生命周期,可以訪問this,不能訪問dom。

  9. beforeMount:組件生命周期

  10. deactivated: 離開緩存組件a,或者觸發(fā)a的beforeDestroy和destroyed組件銷毀鉤子。

  11. mounted:訪問/操作dom。

  12. activated:進入緩存組件,進入a的嵌套子組件(如果有的話)。

  13. 執(zhí)行beforeRouteEnter回調(diào)函數(shù)next。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Vue中鉤子函數(shù)的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

當(dāng)前題目:Vue中鉤子函數(shù)的示例分析
分享路徑:http://muchs.cn/article24/isjdce.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化、營銷型網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作、自適應(yīng)網(wǎng)站網(wǎng)站收錄、響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司