Heim > Web-Frontend > js-Tutorial > Hauptteil

Eine detaillierte Einführung in Hook-Funktionen in Vue

不言
Freigeben: 2018-07-23 10:46:11
Original
2461 Leute haben es durchsucht

Der Inhalt, der in diesem Artikel mit Ihnen geteilt wird, handelt von den Hook-Funktionen von Vue [Routennavigationsschutz, Keep-Alive, Lebenszyklus-Hook]. Er hat einen gewissen Referenzwert.

Vorwort

Wenn es um die Hook-Funktionen von Vue geht, bleiben viele Leute möglicherweise nur bei einigen sehr einfachen und häufig verwendeten Hooks (created,mounted), und wann sind die Unterschiede zwischen ihnen Ich habe nicht sorgfältig studiert, welchen Haken ich verwenden soll, und der Lebenszyklus von Vue ist auch ein relativ häufig vorkommender Testpunkt in Interviews. Die Beantwortung solcher Fragen wird den Menschen also ein gutes Gefühl geben ...

Vue -Router-Navigationsschutz:

Manchmal müssen wir einige Vorgänge über das Routing ausführen, z. B. die häufigste Überprüfung der Anmeldeberechtigung. Wenn der Benutzer die Bedingungen erfüllt, darf er die Navigation eingeben. Brechen Sie den Sprung ab und springen Sie zur Anmeldeseite, um sich anzumelden.

Aus diesem Grund haben wir viele Möglichkeiten, den Navigationsprozess des Routings einzubetten: Global, exklusiv für eine einzelne Route oder auf Komponentenebene , es wird empfohlen, zuerst das Routing-Dokument zu lesen

Globaler Wächter

vue-router verfügt weltweit über drei Wächter:

  1. router.beforeJeder globale Frontwächter vor dem Betreten der Route

  2. router.beforeResolve Global Parsing Guard (2.5.0+) wird aufgerufen, nachdem beforeRouteEnter aufgerufen wird

  3. router.afterEach nachdem der globale Post-Hook die Route

Verwendung :

    // 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 全局后置钩子');
    });
Nach dem Login kopieren
to, from, next Diese drei Parameter:

to und from sind die Routing-Objekte, die

ausführen Geben Sie ein und verlassen Sie es. Das Routing-Objekt bezieht sich auf das Routing-Objekt, das normalerweise über this.$route erhalten wird.

next:Function Dieser Parameter ist eine Funktion und muss aufgerufen werden, sonst kann die Route nicht eingegeben werden (die Seite ist leer).

  • next() gibt die Route ein.

  • next(false): Brechen Sie die Eingaberoute ab und setzen Sie die URL-Adresse auf die ausgehende Routing-Adresse zurück (d. h. die Routing-Adresse, die übrig bleiben soll).

  • next springt zu einer neuen Route, die aktuelle Navigation wird unterbrochen und eine neue Navigation erneut gestartet.

    Wir können so springen: next('path address') or next({path:''}) or next({name:''})

    und Einstellungen wie replace: true zulassen , Optionen wie Name: 'home'
    und Objektoptionen, die Sie in router-link oder router.push verwenden.

Routenexklusive Wachen

Wenn Sie Wachen nicht global konfigurieren möchten, können Sie Wachen separat für bestimmte Routen konfigurieren:

    const router = new VueRouter({
      routes: [
        {
          path: '/foo',
          component: Foo,
          beforeEnter: (to, from, next) => { 
            // 参数用法什么的都一样,调用顺序在全局前置守卫后面,所以不会被全局守卫覆盖
            // ...
          }
        }
      ]
    })
Nach dem Login kopieren
In Die Routing-Komponente schützt:

  1. beforeRouteEnter vor Eingabe der Route

  2. beforeRouteUpdate (2.2) Beim Routing wird dieselbe Komponente wiederverwendet

  3. beforeRouteLeave Beim Verlassen der aktuellen Route

Einleitung in der Dokumentation:

  beforeRouteEnter (to, from, next) {
    // 在路由独享守卫后调用 不!能!获取组件实例 `this`,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用 可以访问组件实例 `this`
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用,可以访问组件实例 `this`
  }
Nach dem Login kopieren

beforeRouteEnter access this

Da der Hook aufgerufen wird, bevor die Komponenteninstanz erstellt wird, kann die Komponenteninstanz

nicht abgerufen werden. Sie können auf die Komponenteninstanz this zugreifen, indem Sie einen Rückruf an next übergeben.

Aber der Ausführungszeitpunkt des

-Rückrufs liegt hinter mount, daher ist der Zugriff hierauf meiner Meinung nach nicht sehr aussagekräftig und kann innerhalb von oder created platziert werden. mounted

    beforeRouteEnter (to, from, next) {
    console.log('在路由独享守卫后调用');
      next(vm => {
        // 通过 `vm` 访问组件实例`this` 执行回调的时机在mounted后面,
      })
    }
Nach dem Login kopieren

beforeRouteLeave:

Wird aufgerufen, wenn die Navigation die entsprechende Route dieser Komponente verlässt. Wir verwenden es, um zu verhindern, dass der Benutzer sie verlässt, z. B. vor dem Speichern des Entwurfs. oder bevor der Benutzer geht, zerstören Sie

, um zu verhindern, dass der Timer nach dem Verlassen noch aufgerufen wird. setInterval

    beforeRouteLeave (to, from , next) {
      if (文章保存) {
        next(); // 允许离开或者可以跳到别的路由 上面讲过了
      } else {
        next(false); // 取消离开
      }
    }
Nach dem Login kopieren
Einige Kenntnisse über Hooks:

Fehlererkennung der Routing-Hook-Funktion

Wenn wir in der Hook-Funktion von Global Guard/Route Exclusive Guard/Component Route Guard Fehler haben, können Fehler auftreten wie folgt erfasst werden:

    router.onError(callback => { 
    // 2.4.0新增 并不常用,了解一下就可以了 
      console.log(callback, 'callback');
    });
Nach dem Login kopieren
Es gibt weitere Instanzmethoden im Routing-Dokument: dynamisches Hinzufügen von Routen usw. Wenn Sie interessiert sind, können Sie sich darüber informieren.

Springe zu einer Endlosschleife, die Seite ist immer leer

Ich verstehe, dass viele Menschen auf dieses Problem stoßen werden. Schauen Sie sich diesen Pseudocode an:

    router.beforeEach((to, from, next) => {
      if(登录){
         next()
      }else{
          next({ name: 'login' }); 
      }
    });
Nach dem Login kopieren
Schauen Sie sich an die Logik Es scheint richtig zu sein, aber wenn wir zu

springen, springen wir zu login und machen dann eine Endlosschleife. Die Seite wird immer leer sein, also: wir Sie müssen die Beurteilungsbedingung festlegen. Ändern Sie sie ein wenig. login

    if(登录 || to.name === 'login'){ next() } // 登录,或者将要前往login页面的时候,就允许进入路由
Nach dem Login kopieren
Zum globalen Beitrags-Hook springen:

Das Dokument erwähnt, dass router.afterEach die Funktion

nicht akzeptiert und dadurch die Navigation selbst nicht ändert, was bedeutet, dass dies nur der Fall sein kann Wird als Hook verwendet, aber als ich es selbst ausprobiert habe, habe ich festgestellt, dass wir den Sprung in dieser Form erreichen können: next

    // main.js 入口文件
    import router from './router'; // 引入路由
    router.afterEach((to, from) => {
      if (未登录 && to.name !== 'login') {
        router.push({ name: 'login' }); // 跳转login
      }
    });
Nach dem Login kopieren
Nun, es kann auch über router.beforeEach erreicht werden und ist besser, ich wird angeben.

Vollständiger Prozess der Routennavigation (mit Ausnahme anderer Lebenszyklen):

  1. Eintritt zu anderen Routen auslösen.

  2. Rufen Sie den Komponentenwächter an, um die Route zu verlassen

    beforeRouteLeave

  3. Rufen Sie den Präfixwächter an:

    beforeEach

  4. Aufruf

    beforeRouteUpdate

  5. Call Route Exclusive Guard

    in der wiederverwendeten Komponente. beforeEnter

  6. 解析异步路由组件。

  7. 在将要进入的路由组件中调用beforeRouteEnter

  8. 调用全局解析守卫 beforeResolve

  9. 导航被确认。

  10. 调用全局后置钩子的 afterEach 钩子。

  11. 触发DOM更新(mounted)。

  12. 执行beforeRouteEnter 守卫中传给 next 的回调函数

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

在开发Vue项目的时候,大部分组件是没必要多次渲染的,所以Vue提供了一个内置组件keep-alive缓存组件内部状态,避免重新渲染,文档在这里。

文档:和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。

用法:

缓存动态组件:

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们,此种方式并无太大的实用意义。

    <!-- 基本 -->
    <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>
Nach dem Login kopieren

缓存路由组件:

使用keep-alive可以将所有路径匹配到的路由组件都缓存起来,包括路由组件里面的组件,keep-alive大多数使用场景就是这种。

    <keep-alive>
        <router-view></router-view>
    </keeo-alive>
Nach dem Login kopieren

生命周期钩子:

这篇既然是Vue钩子函数的专场,那肯定要扣题呀~

在被keep-alive包含的组件/路由中,会多出两个生命周期的钩子:activateddeactivated

文档:在 2.2.0 及其更高版本中,activated 和 deactivated 将会在 <keep-alive> 树内的所有嵌套组件中触发。

activated在组件第一次渲染时会被调用,之后在每次缓存组件被激活时调用

activated调用时机:

第一次进入缓存路由/组件,在mounted后面,beforeRouteEnter守卫传给 next 的回调函数之前调用:

    beforeMount=> 如果你是从别的路由/组件进来(组件销毁destroyed/或离开缓存deactivated)=>
    mounted=> activated 进入缓存组件 => 执行 beforeRouteEnter回调
Nach dem Login kopieren

因为组件被缓存了,再次进入缓存路由/组件时,不会触发这些钩子

    // beforeCreate created beforeMount mounted 都不会触发。
Nach dem Login kopieren

所以之后的调用时机是:

    组件销毁destroyed/或离开缓存deactivated => activated 进入当前缓存组件 
    => 执行 beforeRouteEnter回调
    // 组件缓存或销毁,嵌套组件的销毁和缓存也在这里触发
Nach dem Login kopieren

deactivated:组件被停用(离开路由)时调用

使用了keep-alive就不会调用beforeDestroy(组件销毁前钩子)和destroyed(组件销毁),因为组件没被销毁,被缓存起来了

这个钩子可以看作beforeDestroy的替代,如果你缓存了组件,要在组件销毁的的时候做一些事情,你可以放在这个钩子里。

如果你离开了路由,会依次触发:

    组件内的离开当前路由钩子beforeRouteLeave =>  路由前置守卫 beforeEach =>
    全局后置钩子afterEach => deactivated 离开缓存组件 => activated 进入缓存组件(如果你进入的也是缓存路由)
    // 如果离开的组件没有缓存的话 beforeDestroy会替换deactivated 
    // 如果进入的路由也没有缓存的话  全局后置钩子afterEach=>销毁 destroyed=> beforeCreate等
Nach dem Login kopieren

那么,如果我只是想缓存其中几个路由/组件,那该怎么做?

缓存你想缓存的路由:

Vue2.1.0之前:

想实现类似的操作,你可以:

  1. 配置一下路由元信息

  2. 创建两个keep-alive标签

  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 所以下面还要创建一个未缓存的路由视图出口-->
    </router-view>
    //router配置
    new Router({
      routes: [
        {
          path: '/',
          name: 'home',
          component: Home,
          meta: {
            keepAlive: true // 需要被缓存
          }
        },
        {
          path: '/:id',
          name: 'edit',
          component: Edit,
          meta: {
            keepAlive: false // 不需要被缓存
          }
        }
      ]
    });
    Nach dem Login kopieren

Vue2.1.0版本之后:

使用路由元信息的方式,要多创建一个router-view标签,并且每个路由都要配置一个元信息,是可以实现我们想要的效果,但是过于繁琐了点。

幸运的是在Vue2.1.0之后,Vue新增了两个属性配合keep-alive来有条件地缓存 路由/组件。

新增属性:

  • include:匹配的 路由/组件 会被缓存

  • exclude:匹配的 路由/组件 不会被缓存

includeexclude支持三种方式来有条件的缓存路由:采用逗号分隔的字符串形式,正则形式,数组形式。

正则和数组形式,必须采用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>
    
    <!-- 数组 (使用 `v-bind`) -->
    <keep-alive :include="[&#39;a&#39;, &#39;b&#39;]">
      <component :is="view"></component>
    </keep-alive>
Nach dem Login kopieren

但更多场景中,我们会使用keep-alive来缓存路由

<keep-alive include=&#39;a&#39;>
    <router-view></router-view>
</keeo-alive>
Nach dem Login kopieren

匹配规则:

  1. 首先匹配组件的name选项,如果name选项不可用。

  2. 则匹配它的局部注册名称。 (父组件 components 选项的键值)

  3. 匿名组件,不可匹配

比如路由组件没有name选项,并且没有注册的组件名。

  1. 只能匹配当前被包裹的组件,不能匹配更下面嵌套的子组件

比如用在路由上,只能匹配路由组件的name选项,不能匹配路由组件里面的嵌套组件的name选项。

  1. 文档:<keep-alive> 不会在函数式组件中正常工作,因为它们没有缓存实例。

  2. exclude的优先级大于include

也就是说:当includeexclude同时存在时,exclude生效,include不生效。

  <keep-alive include="a,b" exclude="a">
    <!--只有a不被缓存-->
    <router-view></router-view>
  </keep-alive>
Nach dem Login kopieren

当组件被exclude匹配,该组件将不会被缓存,不会调用activateddeactivated


组件生命周期钩子:

关于组件的生命周期,是时候放出这张图片了:


这张图片已经讲得很清楚了,很多人这部分也很清楚了,大部分生命周期并不会用到,这里提一下几点:

  1. ajax请求最好放在created里面,因为此时已经可以访问this了,请求到数据就可以直接放在data里面。

    这里也碰到过几次,面试官问:ajax请求应该放在哪个生命周期。

  2. 关于dom的操作要放在mounted里面,在mounted前面访问dom会是undefined

  3. 每次进入/离开组件都要做一些事情,用什么钩子:

  • 不缓存:

    进入的时候可以用createdmounted钩子,离开的时候用beforeDestorydestroyed钩子,beforeDestory可以访问thisdestroyed不可以访问this

  • 缓存了组件:

    缓存了组件之后,再次进入组件不会触发beforeCreatecreatedbeforeMountmounted如果你想每次进入组件都做一些事情的话,你可以放在activated进入缓存组件的钩子中

    同理:离开缓存组件的时候,beforeDestroydestroyed并不会触发,可以使用deactivated离开缓存组件的钩子来代替。

触发钩子的完整顺序:

将路由导航、keep-alive、和组件生命周期钩子结合起来的,触发顺序,假设是从a组件离开,第一次进入b组件:

  1. beforeRouteLeave:路由组件的组件离开路由前钩子,可取消路由离开。

  2. beforeEach: 路由全局前置守卫,可用于登录验证、全局路由loading等。

  3. beforeEnter: 路由独享守卫

  4. beforeRouteEnter: 路由组件的组件进入路由前钩子。

  5. beforeResolve:路由全局解析守卫

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

  7. beforeCreate:组件生命周期,不能访问this

  8. created:组件生命周期,可以访问this,不能访问dom。

  9. beforeMount:组件生命周期

  10. deactivated: 离开缓存组件a,或者触发a的beforeDestroydestroyed组件销毁钩子。

  11. mounted:访问/操作dom。

  12. activated:进入缓存组件,进入a的嵌套子组件(如果有的话)。

  13. 执行beforeRouteEnter回调函数next。

结语

Vue提供了很多钩子,但很多钩子我们几乎不会用到,只有清楚这些钩子函数的触发顺序以及背后的一些限制等,这样我们才能够正确的使用这些钩子,希望看了本文的同学,能对这些钩子有更加清晰的认识,使用起来更加得心应手。

相关推荐:

AngularJs中model、Controller(控制器)和View(视图)之间有什么样的关系?(图文)

Vue自定义指令及指令定义函数的具体分析(代码)

Das obige ist der detaillierte Inhalt vonEine detaillierte Einführung in Hook-Funktionen in Vue. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage