Basic vue-router knowledge and working principle, basic vue-router knowledge

Source: Internet
Author: User

Basic vue-router knowledge and working principle, basic vue-router knowledge

Preface

I was asked about the dynamic route of vue during the interview today. I didn't answer the question, and I felt that it was not a rare question. I haven't read the vue-router document for a long time. Many of the things and concepts I use are not correct. When I come back, I am dumpfounded to see what dynamic routing is. It seems necessary to summarize the knowledge of vue-router.

How a single page application works

I understand the working principle of a single page is that the hash changes after the browser URL # will cause the page to change the features to divide the page into different small modules, then, modify the hash to display the content we want to see on the page.

Why does hash affect page display? What does the browser do here. In the past, the content following # is usually used as an anchor, but it is located at a certain position on a page. How does this happen? What is the difference between it and our current route. (I can think of a route to hide other routes. Is that true?) I will take a look at this question later. Now, the most important thing is to familiarize myself with the basic concepts.

Body

When you want to add vue-router, what we need to do is map the components (components) to the routes, and then tell the vue-router where to render them.

Start

// *** The router-link command tells the browser which route to go to. // *** the router-view Command tells the browser where the route is displayed. <div id = "app"> 

Dynamic Route matching

Similar to the same component. Because different parameters display different component content, the dynamic path parameter is used in the route path of vue-router 』

Const router = new VueRouter ({routes: [// The Dynamic path parameter starts with a colon {path: '/user/: id', component: User}]})

Then we enteruesr/001 Anduser/002 In fact, it is the same route to enter. Different content can be displayed on the Content Page according to different parameters. General application scenarios: List and permission Control

It is defined as dynamic routing.

Use {{ $route.params.id }} To get the parameters in the route.

When Routing Parameters are used, such as navigating from/user/foo to/user/bar, the original component instance will be reused. Because both routes render the same component, reuse is more efficient than destruction. However, this also means that the lifecycle hook of the component will not be called again.

When reusing components and responding to changes in route parameters, you can simply watch (monitor changes) $ route object

Const User = {template: '...', watch: {'$ route' (to, from) {// responds to route changes ...}}}

Sometimes, the same path can match multiple routes. In this case, the matching priority is defined in the order of routes: who first defines, who has the highest priority.

Nested Routing

Nest a route in a route

// <Router-view> appears in the route. This is where the nested route displays content. const User = {template: '<div class = "user"> 

Set an empty route. When no route is specified, the content of the empty route is displayed.

Const router = new VueRouter ({routes: [{path: '/user/: id', component: User, children: [// when/user/: id matches successfully, // UserHome will be rendered in the User's <router-view> {path: '', component: UserHome},]})

Programmatic navigation

Declarative: <router-link: to = "...">
Programming: router. push (...)

As you can imagine, a programmatic push can be understood as pushing a new hash to the browser's history, resulting in a route change.

Router. replace () modifies the route but does not exist in the history
Router. go (n) is a bit like window. history. go (n) of JS)

A named route defines a name for each route.

Naming View

Sometimes you want to display multiple views at the same time (at the same level), instead of nested display. For example, you can create a layout with two views: sidebar (side navigation) and main (main content, in this case, the naming view comes in handy. You can have multiple individually named views on the interface, instead of only one single exit. If no name is set for router-view, the default value is default.

<router-view class="view one"></router-view><router-view class="view two" name="a"></router-view><router-view class="view three" name="b"></router-view>

A view uses one component for rendering. Therefore, multiple views require multiple components for the same route. Make sure that the correct components configuration (with s) is used ):

const router = new VueRouter({ routes: [  {   path: '/',   components: {    default: Foo,    a: Bar,    b: Baz   }  } ]})

Redirection and alias

Redirection is also completed through routes configuration. The following example is to redirect from/a to/B:

const router = new VueRouter({ routes: [  { path: '/a', redirect: '/b' } ]})

You can redirect to other places on the homepage.

The redirection target can also be a named route:

const router = new VueRouter({ routes: [  { path: '/a', redirect: { name: 'foo' }} ]})

It is even a method that dynamically returns the redirection target:

Const router = new VueRouter ({routes: [{path: '/A', redirect: to =>{// method to receive the target route as the parameter // return redirected string path/path object}]})

"Redirection" means that when a user accesses/a, the URL will be replaced with/B and then matched with/B. What is the "alias?

The alias for/a is/B, which means that when the user accesses/B, the URL will remain as/B, but the route match will be/a, just like the user accesses/.

The corresponding routing configuration above is as follows:

const router = new VueRouter({ routes: [  { path: '/a', component: A, alias: '/b' } ]})

The "alias" function allows you to freely map the UI structure to any URL, instead of being limited by the configured nested Routing Structure.

HTML5 History Mode

Ue-router default hash mode-uses the URL hash to simulate a complete URL. When the URL changes, the page will not be reloaded.

If you do not want an ugly hash, you can use the history mode of the route. This mode makes full use of the history. pushState API to perform URL jump without re-loading the page.

const router = new VueRouter({ mode: 'history', routes: [...]})

When you use the history mode, the URL is like a normal url, such as http://yoursite.com/user/id!

However, this mode requires background configuration support. Because our application is a single page client application, if the background does not have the correct configuration, when the user directly accesses the http://oursite.com/user/id in the browser will return 404, this does not look good.

Therefore, you need to add a candidate resource on the server to cover all situations: If the URL does not match any static resources, the same index.html page should be returned, this page is the page on which your app depends.

Give a warning, because after this operation, your server will no longer return the 404 error page, because the index.html file will be returned for all paths. To avoid this situation, you should overwrite all routing conditions in the Vue application, and then provide a 404 page.

const router = new VueRouter({ mode: 'history', routes: [  { path: '*', component: NotFoundComponent } ]})

Alternatively, if you use the Node. js server, you can use the server route to match the incoming URL and return 404 if no route is matched.

Navigation guard

My understanding is the hook function of components or global components.

As its name suggests, the navigation guard provided by vue-router is mainly used to guard the navigation by means of jump or cancellation. There are multiple opportunities to implant the route navigation process: Global, exclusive to a single route, or component-level.

Remembering the changes to parameters or queries does not trigger navigation guards that enter/exit. You can observe the $ route object to cope with these changes, or use the beforeRouteUpdate component to guard.

Global guard

const router = new VueRouter({ ... })router.beforeEach((to, from, next) => { // ...})

Each guard method receives three parameters:

To: Route: Target Route object to be entered

From: Route: the Route from which the current navigation is about to exit

Next: Function: You must call this method to resolve the hook. The execution result depends on the call parameters of the next method.

Next (): Perform the next hook in the pipeline. If all the hooks are finished, the navigation status is confirmed (confirmed ).

Next (false): interrupt the current navigation. If the URL of the browser changes (either manually or backward), the URL address is reset to the address corresponding to the from route.

Next ('/') or next ({path: '/'}): jump to a different address. The current navigation is interrupted and a new navigation is performed. You can pass any location object to next, and set options such as replace: true, name: 'home', and any to prop or router used in router-link. options in push.

Next (error): (2.4.0 +) if the parameter passed in next is an Error instance, the navigation will be terminated and the error will be passed to the router. onError () registered callback.

Make sure you want to call the next method, otherwise the hook will not be resolved.

Global rear hook

You can also register a global posthook. However, unlike guard, these hooks do not accept the next function or change the navigation itself:

router.afterEach((to, from) => { // ...})

Dedicated route guard

You can directly define the beforeEnter guard in the route Configuration:

const router = new VueRouter({ routes: [  {   path: '/foo',   component: Foo,   beforeEnter: (to, from, next) => {    // ...   }  } ]})

These guards have the same method parameters as the global front guard.

Component guard

Finally, you can define the following route navigation guards in the routing component:

BeforeRouteEnter beforeRouteUpdate (New in 2.2) beforeRouteLeaveconst Foo = {template :'... ', beforeRouteEnter (to, from, next) {// called before the corresponding route for rendering the component is confirm // No! Yes! Obtain the component instance 'it' // because the component instance has not been created before the guard is executed}, beforeRouteUpdate (to, from, next) {// Changes in the current route, however, when the component is called again // For example, for a path with dynamic parameters/foo/: id, when the jump between/foo/1 and/foo/2, // component instances will be reused because the same Foo component will be rendered. This hook will be called in this case. // You can access the component instance 'eas'}, beforeRouteLeave (to, from, next) {// call when the corresponding route of the component is left in the navigation bar // you can access the component instance 'eas '}}

BeforeRouteEnter guard cannot access this because the guard is called before navigation confirmation, so the new component to be launched has not yet been created.

Complete navigation parsing process

The navigation is triggered.
Call exit guard in inactive components.
Call the global beforeEach guard.
Call beforeRouteUpdate guard (2.2 +) in reusable components ).
Call beforeEnter in route configuration.
Parses the asynchronous routing component.
Call beforeRouteEnter in the activated component.
Call the global beforeResolve guard (2.5 + ).
The navigation is confirmed.
Call the global afterEach hook.
Trigger DOM update.
Use the created instance to call the callback function passed to next in the beforeRouteEnter guard.

Route metadata

My understanding is that he can list all the parent paths of the route and complete some tasks, such as logon and logon for the user component. The foo component under the user also needs, this attribute can be used to check the status of the route.

You can configure the meta field when defining a route:

const router = new VueRouter({ routes: [  {   path: '/foo',   component: Foo,   children: [    {     path: 'bar',     component: Bar,     // a meta field     meta: { requiresAuth: true }    }   ]  } ]})

First, we call each route object in the routes configuration as a route record. Route records can be nested. Therefore, when a route is successfully matched, it may match Multiple Route records.

For example, according to the preceding route configuration, the URL/foo/bar matches the parent route record and child route record.

All route records matched by a route will be exposed to the $ route. matched array of $ route objects (and routing objects in the navigation Guard. Therefore, we need to traverse$route.matched To check the meta field in the route record.

The following example shows how to check the meta field in the global navigation GUARD:

Router. beforeEach (to, from, next) => {if (. matched. some (record => record. meta. requiresAuth) {// this route requires auth, check if logged in // if not, redirect to login page. if (! Auth. loggedIn () {next ({path: '/login', query: {redirect:. fullPath})} else {next () // make sure to call next ()}})

Data Acquisition

My understanding is where to get the data. You can either access the component or the component guard, that is, the life cycle of the component.

Sometimes, after entering a route, you need to obtain data from the server. For example, when rendering user information, you need to obtain user data from the server. We can achieve this in two ways:

Obtain data after navigation: complete navigation and then obtain data in the following component lifecycle hooks. Displays instructions such as "loading" during data acquisition.

Obtain data before navigation: Before the navigation is complete, obtain data from the ingress guard and perform navigation after the data is obtained successfully.

From a technical point of view, both methods are good-depending on the user experience you want.

Retrieve data after navigation

When you use this method, we will immediately navigate and render the component, and then get the data in the created hook of the component. This gives us the opportunity to display a loading status during data acquisition, as well as different loading statuses between different views.

Assume that we have a Post component, and we need to get the article data based on $ route. params. id:

<Template> <div class = "post"> <div class = "loading" v-if = "loading"> Loading... </div> <div v-if = "error" class = "error" >{{ error }}</div> <div v-if = "post" class =" content "> 

Get data before navigation

In this way, we obtain data before navigation to the new route. We can retrieve data in the beforeRouteEnter guard of the following component. After the data is obtained successfully, only the next method is called.

Export default {data () {return {post: null, error: null }}, beforeRouteEnter (to, from, next) {getPost (. params. id, (err, post) =>{ next (vm => vm. setData (err, post)}, // before the route change, the component has been rendered. // The logic is slightly different. beforeRouteUpdate (to, from, next) {this. post = null getPost (. params. id, (err, post) =>{ this. setData (err, post) next ()}, methods: {setData (err, post) {if (err) {this. error = err. toString ()} else {this. post = post }}}}

When obtaining data for the following view, the user will stay on the current interface. Therefore, it is recommended that some progress bars or other instructions be displayed during data acquisition. If data acquisition fails, it is also necessary to display some global Error alerts.

Summary

The above section describes basic vue-router knowledge and working principles. I hope it will be helpful to you. If you have any questions, please leave a message for me, the editor will reply to you in a timely manner. Thank you very much for your support for the help House website!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.