preface

When it comes to Vue’s hook functions, many people may only stick to some simple and commonly used hooks (created,mounted), and have not carefully studied the differences and when to use what hooks. Moreover, the life cycle of Vue is also a high-frequency test point in the interview, so how to answer such questions? Let a person have a bright feeling…

Front-end advanced accumulation, public account, GitHub


Vue-router Navigation Guard:

Sometimes, we need to do something with the route, such as the most common login authentication, when the user meets the criteria, let him go to the navigation, otherwise cancel the jump and jump to the login page for him to log in.

There are many ways to embed the route navigation process: globally, individually, or at the component level. It is recommended that you read the routing document first

Global guard

The vue-Router global has three guards:

  1. Router. beforeEach Before the global front guard enters the route
  2. The Router. beforeResolve Global Resolution Guard (2.5.0+) is called after the beforeRouteEnter call
  3. Router. afterEach After the global afterhook enters the route

Usage:

// main.js import router from './router'; // Import router. BeforeEach ((to, from, next) => {next(); }); router.beforeResolve((to, from, next) => { next(); }); Router.aftereach ((to, from) => {console.log('afterEach global hook '); });Copy the code

The three arguments to,from, and next:

To and from are the route objects to enter and to leave. The route object is the route object normally obtained through this.$route.

Next :Function This argument is a Function, and must be called, otherwise can not enter the route (blank page).

  • Next () enters the route.

  • Next (false): Cancel the entry route, and the URL is reset to the from route address (that is, the route to leave).

  • Next hops to the new route. The current navigation is interrupted and a new navigation is started.

    We can jump to: next('path address ') or next({path:''}) or next({name:''}) and allow Settings such as replace: true, name: Options like 'home' and the object options you use for router-link or router-. push.Copy the code

Route exclusive guard

If you don’t want to configure the guard globally, you can configure the guard separately for certain routes:

const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => {// the call sequence is the same as the global front guard, so it is not overwritten by the global guard //...}}]})Copy the code

Guards within the routing component:

  1. BeforeRouteEnter Before the route enters
  2. BeforeRouteUpdate (2.2) When routing is multiplexed with the same component
  3. BeforeRouteLeave When the current route is left

Introduction in the document:

BeforeRouteEnter (to, from, next) {// call after routing exclusive guard no! Can!!!! }, beforeRouteUpdate (to, from, next) {// When the current route changes, but the component is being reused, the call can access the component instance 'this' // For example, For a path with dynamic parameters /foo/:id, jumping between /foo/1 and /foo/2, // will render the same component foo, so component instances will be reused. The hook will be called in that case. }, beforeRouteLeave (to, from, next) {// called when navigating away from the corresponding route of the component, to access the component instance 'this'}Copy the code

BeforeRouteEnter access this

Because the hook is called when the component instance has not yet been created, the component instance this cannot be retrieved. Instead, the component instance can be accessed by passing a callback to next.

However, the callback is executed after Mounted, so I don’t see the significance of accessing this here. It can be placed in created or Mounted.

BeforeRouteEnter (to, from, next) {console.log(' called after routing exclusive guard '); Next (vm => {// select 'this' from' vm 'where' this' is mounted,})}Copy the code

BeforeRouteLeave:

When navigating away from the corresponding route of the component, we use it to prevent the user from leaving, for example, before the draft is saved, or to destroy the setInterval before the user leaves so that the timer is not called after the user has left.

BeforeRouteLeave (to, from, next) {if (save the article) {next(); } else {next(false); // Cancel leave}}Copy the code

A few things about hooks:

Error capture of route hook function

If we have an error in the global guard/routing exclusive guard/component routing guard hook function, we can catch it like this:

Router. onError(callback => {// console.log(callback, 'callback'); });Copy the code

There are many more instance methods in the routing document, such as dynamically adding routes.

Jump endless loop, the page is always blank

I’ve learned that a lot of people run into this problem, so let’s look at this pseudocode:

Router-.beforeeach ((to, from, next) => {if(login){next()}else{next({name: 'login'}); }});Copy the code

The logic seems to be correct, but when we jump to login, because we are still not logged in at this time, we will jump to login and then loop endlessly, and the page is always blank, so: we need to change the judgment conditions a little.

If (login | | to.. name = = = 'login') {next ()} / / login, or are going to go to the login page, is allowed to enter the routingCopy the code

Jump to global rear hooks:

The documentation mentions that since router-aftereach does not accept the next function, it does not change the navigation itself, which means that it can only be used as a hook, but I found out in my own testing that we can use this form to make a jump:

// main.js import router from './router'; AfterEach ((to, from) => {if (not logged in && to.name! == 'login') { router.push({ name: 'login' }); // Jump login}});Copy the code

Well, this can be done completely and better with router.beforeeach.

Complete route navigation resolution process (excluding other life cycles) :

  1. Other routes are triggered.
  2. Calls the component guard to leave the routebeforeRouteLeave
  3. Calling the bureau front guard:beforeEach
  4. Called in a reused componentbeforeRouteUpdate
  5. Call route exclusive guardbeforeEnter.
  6. Resolve the asynchronous routing component.
  7. Called in the incoming routing componentbeforeRouteEnter
  8. Call the global resolution guardbeforeResolve
  9. Navigation is confirmed.
  10. That calls the global post-hookafterEachHook.
  11. Trigger a DOM update (mounted).
  12. performbeforeRouteEnterThe callback function passed to next from the guard

You don’t know keep-alive[I guess you don’t know]

When developing Vue projects, it is not necessary for most components to be rendered more than once, so Vue provides a built-in component keep-Alive to cache the internal state of components and avoid re-rendering. The document is here.

Document: Like
,

is an abstract component: it does not render a DOM element by itself, nor does it appear in the parent component chain.

Usage:

Cache dynamic components:


, when wrapping dynamic components, caches inactive component instances instead of destroying them, which is not very practical.

<! Basic -- > - < keep alive - > < component: is = "view" > < / component > < / keep alive - > <! - multiple conditions determine child components -- > < keep alive - > < comp - a v - if = a > "1" > < / comp - > a < comp - b v - else > < / comp - b > < / keep alive - >Copy the code

Cache routing components:

Keep-alive caches all routing components matched to a path, including components within the routing component. This is what keep-alive is used for in most scenarios.

    <keep-alive>
        <router-view></router-view>
    </keep-alive>
Copy the code

Lifecycle hooks:

Vue hook function (Vue hook function (Vue hook function)

In components/routes that are kept alive, there are two additional lifecycle hooks: Activated and deactivated.

Documentation: In 2.2.0 and later, Activated and deactivated will be triggered in all nested components in the tree.

Activated is called the first time the component is rendered, and then every time the cache component is activated.

Call time of Activated:

The first time a cached route/component is entered, after Mounted, beforeRouteEnter is called before the guard passes the callback function to next:

BeforeMount => If you are coming in from another route/component (the component destroyed/ left the cache deactivated)=> Mounted => Activated to enter the cache component => execute the beforeRouteEnter callbackCopy the code

Because the component is cached, these hooks will not be triggered when the cached route/component is re-entered:

BeforeCreate Created beforeMount Mounted Is not triggered.Copy the code

So the next call time is:

Deactivated => Activated enters the current cache component => execute the beforeRouteEnter callback // Component cache or destroy. Destruct and cache of nested components are also triggered hereCopy the code

Deactivated: invoked when a component is disabled (off the route)

BeforeDestroy and Destroyed are not called when keep-alive is used because the component is not destroyed, it is cached.

This hook can be seen as an alternative to beforeDestroy. If you cache a component and want to do something when the component is destroyed, you can put it in this hook.

If you leave the route, it triggers in turn:

BeforeRouteLeave => route front guard beforeEach => global post hook afterEach => deactivated If the component leaves the cache => activated Enter the cache component (if you entered a cached route) // beforeDestroy replaces deactivated if the departing component is not cached // afterEach=> Destroy an incoming route => BeforeCreate etc.Copy the code

So, what if I just want to cache a few of these routes/components?

Cache the routes you want to cache:

Vue2.1.0 before:

To do something similar, you can:

  1. Configure the routing meta information

  2. Create two keep-alive tags

  3. The v-if command is used to determine which routes to cache based on the routing meta information.

    <keep-alive> <router-view v-if="$route.meta.keepAlive"> <! </router-view> </keep-alive> <router-view v-if="! $route.meta.keepAlive"> <! New router ({routes: [{path: '/', name:]) {route: [{path: '/', name:] {route: [{path: '/', name:]}} }}, {path: '/:id', name: 'edit', Component: Edit, meta: {keepAlive: true // Needs to be cached}}, {path: '/:id', name: 'edit', Component: Edit, meta: {keepAlive: false // does not need to be cached}}]});Copy the code

After Vue2.1.0:

Using routing meta information, creating a router-view tag and configuring a meta information for each route, can achieve the desired effect, but it is too tedious.

Fortunately, since Vue2.1.0, Vue has added two properties that work with keep-alive to conditionally cache routes/components.

New properties:

  • include: The matched routes/components are cached
  • exclude: The matched routes/components are not cached

Include and exclude support conditional caching of routes in three ways: as a comma-separated string, in a regular format, and in an array.

Regular and array forms must be used in the V-bind form.

How to use the cache component:

<! -- comma-separated strings --> <keep-alive include="a,b"> <component :is="view"></component> </keep-alive> <! - regular expressions (using ` v - bind `) - > < keep alive: - include = "/ a | b/" > < component: is =" view "> < / component > < / keep alive - > <! - array (using ` v - bind `) - > < keep alive: - include = "(' a ', 'b')" > < component: is = "view" > < / component > < / keep alive - >Copy the code

But more often than not, we use keep-alive to cache routes:

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

Matching rules:

  1. The name option of the component is first matchedIf thenameOptions are not available.
  2. Matches itsLocally registered name. (parent componentcomponentsOption key)
  3. Anonymous component, no match.

For example, the routing component has no name option and no registered component name.

  1. Matches only the currently wrapped component, and does not match sub-components nested further down.

For example, when used on a route, only the name option of the routing component matches, but not the name option of the nested components in the routing component.

  1. Documents:<keep-alive>Does not work properly in functional componentsBecause they have no cache instances.
  2. excludeThe priority of is greater thaninclude

That is, when both include and exclude exist, exclude takes effect and include does not.

<keep-alive include="a,b" exclude="a"> <! </router-view> </router-view> </keep-alive>Copy the code

When a component matches exclude, the component is not cached and does not call Activated or deactivated.


Component lifecycle hooks:

About component lifecycle, it’s time to release this image:

This picture is pretty clear, and many people are pretty clear on this part, most of the life cycle is not going to be used, so here are a few things:

  1. Ajax requests are best placed in created, because this is already available, and the data requested can be placed directly in data.

    A few times here, the interviewer asks in which lifecycle the Ajax request should be placed.

  2. Operations on the DOM should be placed inside mounted, and access to the DOM before mounted is undefined.

  3. Do something each time you enter/leave a component, with what hooks:

  • Don’t cache:

    You can use created and Mounted hooks to enter, and you can use beforeDestory and Destroyed hooks to leave. BeforeDestory can access this, and Destroyed cannot access this.

  • Caches components:

    If you want to do something every time you enter the component, you can put activated in the hook for entering the cache component.

    Also: beforeDestroy and Destroyed do not trigger when leaving the cache component, use deactivated to leave the cache component hook instead.


The full sequence of triggering hooks:

The sequence of firing that combines routing navigation, keep-alive, and component lifecycle hooks, assuming you first enter component B from component A:

  1. beforeRouteLeave: The hook before the component of the routing component leaves the route, which can cancel the route leaving.
  2. beforeEach: Global front guard of routes, which can be used for login authentication and global route loading.
  3. beforeEnter: Route exclusive guard
  4. beforeRouteEnter: Hook before the component of the routing component enters the route.
  5. beforeResolve:Route global resolution guard
  6. afterEach: routes global rear hooks
  7. beforeCreate: Life cycle of the component, which cannot be accessedthis.
  8. created: Component life cycle, accessiblethis, cannot access the DOM.
  9. beforeMount: Component life cycle
  10. deactivated: leaves cache component A, or triggers abeforeDestroyanddestroyedComponent destruction hook.
  11. mounted: Access/operate the DOM.
  12. activated: Goes into the cache component, into a’s nested child component (if any).
  13. Execute the beforeRouteEnter callback function next.

conclusion

Vue offers many hooks, but a lot of hook we hardly used, only clear the hooks order and behind some of the restrictions, etc., so we can properly use these hooks, wish to see in this paper, the classmate, can have a more clear understanding about these hooks, use rise more handy.

I hope that after watching the friends can click like/follow, your support is the biggest encouragement to me.

Front-end advanced accumulation, public account, GitHub, wx:OBkoro1, email: [email protected]

The above 2018.7.21

References:

Vue document

Deep understanding and use of keep-Alive (with router-view to cache entire routing pages)