Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How vue-router works

2025-04-12 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "how vue-router works". Interested friends may wish to take a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how vue-router works.

How single-page applications work

The way I understand how a single page works is to divide the page into different modules through the feature that the hash change after the # of the browser URL will cause the page to change, and then modify the hash to make the page show what we want to see.

So why does the difference in hash affect the presentation of the page? What does the browser do in this? In the past, the content after # used to act as an anchor, but it would be located somewhere on a page. How does this work? how is it different from our current routing? (I can think of a display of routes that will hide other routes, is that right?) I'll take a look at it later and write down this puzzle. The most important thing now is to get familiar with the basic concepts.

Text

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

Start

/ / * router-link tells the browser which route to go / / * router-view tells the route where to display the content Hello App!

Go to Foo Go to Bar

/ / 1. Define (route) components. / / you can enter const Foo = {template: 'foo'} const Bar = {template:' bar'} / / 2 from another file import. Define routes / / each route should map a component. Where "component" can be a component constructor created by Vue.extend (), or just a component configuration object. / / We'll talk about nested routing later. Const routes = [{path:'/ foo', component: Foo}, {path:'/ bar', component: Bar}] / / 3. Create a router instance, and then pass `routes` configuration / / you can also pass other configuration parameters, but let's keep it that simple. Const router = new VueRouter ({routes / / (abbreviated) is equivalent to routes: routes}) / / 4. Create and mount the root instance. / / remember to inject routing through the router configuration parameters, / / so that the entire application has the routing function const app = new Vue ({router}). $mount ('# app') / / now, the application has started!

Dynamic route matching

It is equivalent to the same component, because different parameters show different component contents, in fact, "dynamic path parameters" are used in the routing path of vue-router.

Const router = new VueRouter ({routes: [/ / dynamic path parameters begin with a colon {path:'/ user/:id', component: User}]})

So when we enter uesr/001 and user/002, we actually enter the same route, and we can display different contents on the content page according to different parameters. General applicable scenarios: list, permission control

When defining: indicates that it is a dynamic route

Use {{$route.params.id}} to get the contents of the parameters in this route

When routing parameters are used, such as navigating from / user/foo to / user/bar, the original component instance is reused. Because both routes render the same component, reuse is more efficient than destroying and re-creating. However, this also means that the component's lifecycle hooks will no longer be called.

If you want to respond to changes in routing parameters when reusing components, you can simply watch (monitor changes) $route object

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

Sometimes, the same path can match multiple routes, and at this time, the priority of the match is in the order in which the route is defined: whoever defines it first has the highest priority.

Nested routing

Nest a route within a route

/ / the route will also appear in the place where the nested route is displayed const User = {template: `User {{$route.params.id}} `} / / when the route is defined, add the children sub-route attribute const router = new VueRouter ({routes: [{path:'/ user/:id', component: User, children: [{/ / when / user/:id/profile matches successfully / / UserProfile will be rendered in User path: 'profile', component: UserProfile}, {/ / when / user/:id/posts matches successfully / / UserPosts will be rendered in User path:' posts', component: UserPosts}]})

Set an empty route so that the empty route content is displayed when no route is specified

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

Programmatic navigation

Declarative:

Programmer: router.push (...)

You can imagine that a programmatic push can be understood as push a new hash into the browser history, resulting in a routing change.

Router.replace () modifies the route but does not exist in the history

Router.go (n) is a bit like JS's window.history.go (n)

Named routes define a name for each route.

Named view

Sometimes you want to display multiple views at the same time (at the same level) instead of nested displays, such as creating a layout with sidebar (side navigation) and main (main content) views. Instead of having a single exit, you can have multiple individually named views in the interface. If router-view does not have a name set, it defaults to default.

A view is rendered with one component, so multiple views require multiple components for the same route. Ensure that the components configuration is used correctly (with s):

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

Redirects and aliases

Redirection is also done through routes configuration. The following example is redirection from / a to / b:

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

Usually, you can redirect to another place on the home page.

The target of the redirection can also be a named route:

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

There is even a method that dynamically returns the redirect target:

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

"Redirect" means that when a user visits / a, the URL will be replaced with / b, and then the matching route will be / b, so what is the "alias"?

The alias of / an is / b, which means that when the user accesses / b, the URL remains at / b, but the route match is / a, just as the user accesses / a.

The corresponding routes above are configured as follows:

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

The "alias" feature gives you the freedom to map UI structures to any URL, rather than being limited by the configured nested routing structure.

HTML5 History mode

Ue-router default hash mode-uses URL's hash to simulate a full URL, so when the URL changes, the page does not reload.

If you don't want an ugly hash, you can use the routed history mode, which takes full advantage of history.pushState API to complete the URL jump without reloading the page.

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

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

However, in order to play this mode well, it also needs background configuration support. Because our application is a single-page client application, if the background is not configured correctly, users will return 404 when they directly access http://oursite.com/user/id in the browser, which is not good-looking.

So, you need to add a candidate resource that covers all situations on the server: if the URL does not match any static resources, you should return the same index.html page, which is the page on which your app depends.

Give me a warning, because after doing so, your server will no longer return 404 error pages, because index.html files will be returned for all paths. To avoid this, you should cover all routing situations in the Vue application and then give a 404 page.

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

Or, if you use a Node.js server, you can match the incoming URL with a server-side route and return 404 if there is no match to achieve fallback.

Navigation guard

My understanding is the hook function of a component or a component at the global level

As the name suggests, the navigation guards provided by vue-router are mainly used to guard navigation by jumping or canceling. There are many opportunities to be implanted in the routing navigation process: global, exclusive to a single route, or component-level.

Keep in mind that changes in parameters or queries do not trigger entry / exit navigation guards. You can respond to these changes by observing the $route object, or by using beforeRouteUpdate's in-component guards.

Global guard

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

Each guard method receives three parameters:

To: Route: the destination routing object to be entered

From: Route: the route from which the current navigation is leaving

Next: Function: be sure to call this method to resolve the hook. The execution effect depends on the calling parameters of the next method.

Next (): proceed to the next hook in the pipe. If all the hooks are finished, the navigation status is confirmed (confirmed).

Next (false): interrupts the current navigation. If the URL of the browser changes (either manually by the user or by the browser back button), the URL address is reset to the address of the from route.

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

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

Be sure to call the next method, otherwise the hook will not be resolved.

Global rear hook

You can also register global rear hooks, but unlike guards, these hooks do not accept next functions and do not change the navigation itself:

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

A guard exclusive to routing.

You can define beforeEnter guards directly on the routing 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.

Guards within the component

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

BeforeRouteEnter beforeRouteUpdate beforeRouteLeaveconst Foo = {template: `...`, beforeRouteEnter (to, from, next) {/ / call / / No before rendering the corresponding route of the component by confirm! Yes! Get component instance `this` / / because the component instance has not been created before the guard executes}, beforeRouteUpdate (to, from, next) {/ / changes the current route, but the component is called / / for example, for a path / foo/:id with dynamic parameters, when you jump between / foo/1 and / foo/2, / / because the same Foo component will be rendered So the component instance is reused. And this hook will be called in this case. / / can access component instance `this`}, beforeRouteLeave (to, from, next) {/ / call / / access component instance `this`} when navigating away from the corresponding route of the component

The beforeRouteEnter guard cannot access the this because the guard is called before the navigation is confirmed, so the upcoming new component has not been created.

Complete navigation parsing process

Navigation is triggered.

Call away from the guard in the deactivated component.

Call the global beforeEach guard.

Invoke the beforeRouteUpdate guard (2.2 +) in the reused component.

Call beforeEnter in the routing configuration.

Parse the asynchronous routing component.

Call beforeRouteEnter in the activated component.

Call the global beforeResolve guard (2.5 +).

Navigation confirmed.

Call the global afterEach hook.

Triggers a DOM update.

Call the callback function passed to next in the beforeRouteEnter guard with the created instance.

Routing meta-information

My understanding is that he can list all the parent paths of the route and complete some tasks, such as login, the user component needs to log in, then the foo component under the user also needs, then you can use this attribute to detect some status on the routing line.

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 routing object in the routes configuration a route record. Route records can be nested, so when a route matches successfully, it may match multiple route records

For example, based on the routing configuration above, the / foo/bar URL will match the parent route record as well as the child route record.

All route records to which a route matches are exposed as $route.matched arrays of $route objects (and routing objects in the navigation guard). Therefore, we need to iterate through $route.matched to check the meta field in the routing record.

The following example shows checking meta fields in the global navigation guard:

Router.beforeEach ((to, from, next) = > {if (to.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: to.fullPath}})} else {next ()} else {next () / / make sure next ()}} is called)

Data acquisition

My understanding is where to get the data, either in the component or in the guard of the component, that is, in the lifecycle of the component.

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

Get after the navigation is complete: complete the navigation first, and then get the data in the next component lifecycle hook. Displays an indication such as "loading" during data acquisition.

Get before the navigation is completed: before the navigation is completed, the data is obtained from the guard that routes into, and the navigation is performed after the data acquisition is successful.

From a technical point of view, both approaches are good-depending on what kind of user experience you want.

Get data after navigation is completed

When you use this approach, we will immediately navigate and render the component, and then get the data in the component's created hook. This gives us the opportunity to present a loading state during data acquisition, as well as different loading states between different views.

Suppose we have a Post component that needs to get article data based on $route.params.id:

Loading... {{error}} {{post.title}}

{{post.body}}

Export default {data () {return {loading: false, post: null, error: null}}, created () {/ / the component is created to obtain data, / / at this time the data has been observed this.fetchData ()}, watch: {/ / if the route is changed The method'$route': 'fetchData'} is executed again, methods: {fetchData () {this.error = this.post = null this.loading = true / / replace getPost with your data fetching util / API wrapper getPost (this.$route.params.id, (err, post) = > {this.loading = false if (err) {this.error = err.toString ()} else {this.post = post})}

Get data before navigation is complete

In this way, we get the data before navigating to the new route. We can get the data in the beforeRouteEnter guard of the next component, and only call the next method when the data is successfully obtained.

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

When fetching data for later views, the user will stay in the current interface, so it is recommended that some progress bar or other indication be displayed during data acquisition. If the data acquisition fails, it is also necessary to show some global error reminders.

At this point, I believe you have a deeper understanding of "how vue-router works". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report