Vue-router essentially maps urls to components

Route:

Dynamic routing

We all have our own home page, and we use the same component to display the content of the home page, so we just need to change the id of the user passed in to display the corresponding user content, rather than rewriting a component.

For example: juejin. Cn/user / 449027… ; Change the following ID to be a different user

Const router = new VueRouter({routes: [// dynamic route parameters start with a colon {path: '/user/:id', Component: user}, // multi-route {path: '/user/:id', component: user}, // multi-route {path: '/city/:cityname/house/:house_id', } ] })Copy the code

Path parameters are marked with a colon:. When a route is matched, the parameter value is set to this.$route.params, which can be used within each component.

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}
Copy the code
const City = {
 template: '<div>City {{ $route.params.cityname }} -- House {{house_id}}</div>'
}
Copy the code

Routing change

When routing parameters are used, the original component instance is reused, which is more efficient than destroying and recreating it. However, this also means that the component’s lifecycle hooks are no longer called.

But it triggers the route’s navigational guard: beforeRouteUpdate

There are two methods to detect the change of routing objects:

const User = { template: '... ', watch: {$route(to, from) {$route(to, from) { }}}Copy the code
const User = { template: '... ', beforeRouteUpdate(to, from, next) { // react to route changes... // don't forget to call next() } }Copy the code

Captures an unspecified route

Regular arguments only match characters in URL fragments delimited by /. If we want to match any path that is not specified, we can use the wildcard (*) :

{/ / will match all path path: '*'} {/ / will match with ` / user - ` path at the beginning of arbitrary path: '/ user - *}Copy the code

When using wildcard routes, ensure that the order of routes is correct, that is, routes containing wildcards should be placed last. The route {path: ‘*’} is usually used for client 404 errors.

$route.params automatically adds a parameter named pathMatch. It contains parts of the URL that are matched by wildcards:

// give a route {path: '/user-*'} this.$route.push ('/user- *') this.$route.params.pathMatch // 'admin' // give a route {path: '*' } this.$router.push('/non-existing') this.$route.params.pathMatch // '/non-existing'Copy the code

Embedded routines by

The dynamic path segments in the URL also correspond to nested layer components in a certain structure. With vue-Router, this relationship can be easily expressed using nested routines.

const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, children: [{// If /user/:id/profile matches successfully, // UserProfile will be rendered in user's <router-view> path: 'profile', Component: UserProfile}, {// When /user/:id/posts match successfully // UserPosts will be rendered in user <router-view> path: 'posts', component: UserPosts } ] } ] })Copy the code

Components are nested

 <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
 </div>
Copy the code

Note that nested paths starting with/are treated as root paths. This lets you make full use of nested components without having to set nested paths. The root of a Vue file is a nested path starting with a slash

  <div id="app">
    <router-view/>
  </div>
Copy the code

After routing

You can set the name of a route in the Routes configuration when creating the Router instance.

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})
Copy the code

To link to a named route, pass an object to router-link’s to property:

<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
Copy the code

Named view

Instead of having a single exit, you can have multiple individually named views in the interface. If router-view does not have a name, it defaults to default.

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="helper"></router-view>
Copy the code

You can then complete the layout with this routing configuration:

{path: '/ Settings ', // You can also configure named views on top-level routing. Component: UserSettings, children: [{path: 'emails', Component: UserEmailsSubscriptions }, { path: 'profile', components: { default: UserProfile, helper: UserProfilePreview, a: Loading } }] }Copy the code

Route redirection and alias

redirect

Redirection is also done using the Routes configuration, as shown in the following example:

Const router = new VueRouter({routes: [// redirect from '/a' to '/ b '{path: '/a', redirect: '/b'}, // The redirect target can also be a named route {path: '/c', redirect: {name: 'foo'}}, // even a method that dynamically returns the redirect target {path: '/a', redirect: To => {// method receives destination route as argument // return redirected string path/path object}}]})Copy the code

Note: Redirection does not trigger the navigation guard

The alias

Just like people’s nicknames, although the name is different, but you are still you; The same goes for routes, which have different pathnames but still jump to the same component

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

Programmatic routing

Instead of using

to create an A tag to define navigation links, we can use the router instance method to write code to do so.

Note: Inside the Vue instance, you can access the routing instance through $router.

Router object methods

$router.push()

To navigate to different urls, use the router.push method. This method adds a new record to the history stack, so when the user clicks the browser back button, it returns to the previous URL.

Click on the<router-link :to="..." >Equivalent to callingrouter.push(...).

router.push(location, onComplete? , onAbort?)

The argument to this method can be a string path or an object describing the address. Such as:

Router.push ('home') // Object router.push({path: 'home'}) // Named route Router.push ({name: 'user', params: {userId: '123'}}) // change to /register? plan=private router.push({ path: 'register', query: { plan: 'private' }}) const userId = '123' router.push({ name: 'user', params: { userId }}) // -> /user/123 router.push({ path: ` ` / user / ${username}}) / / - > / user / 123 / / params does not effect the router here. Push ({path: '/ user' params: {username}}) / / - > / userCopy the code
$router.replace()

Much like router.push, it does not add a new record to history, but replaces the current history record with its method name.

The usage is the same

$router.go()

This method takes an integer that means how many steps forward or backward in the history, similar to window.history.go(n).

Forward () router.go(1) // Back () router.go(-1)Copy the code

History native method

If you’re already familiar with the Browser History APIs (opens New Window), manipulating History in the Vue Router is super simple.

It is also worth mentioning that the navigation methods of Vue Router (push, replace, go) are consistent in all routing modes (history, Hash, and abstract).

Routing and the cords

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
  routes: [{ path: '/user/:id', component: User }]
})
Copy the code

Using $route in a component makes it highly coupled to its corresponding route, limiting its flexibility by limiting its use to certain urls.

Decoupled by props

const User = { props: ['id'], template: '<div>User {{ id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', Component: user, props: true}, // For routes that contain named views, you must add 'props' options for each named view: {path: '/user/:id', components: { default: User, sidebar: Sidebar }, props: { default: true, sidebar: false } } ] })Copy the code

Boolean value

If props is set to true, route.params will be set to the component property.

Object values

If props were an object, it would be set as a component property as is. This is useful when props is static.

The function mode

You can create a function that returns props. This allows you to convert parameters to another type, combine static values with route-based values, and so on.

const router = new VueRouter({
  routes: [
    {
      path: '/search',
      component: SearchUser,
      props: route => ({ query: route.query.q })
    }
  ]
})
Copy the code

URL /search? Q =vue passes {query: ‘vue’} as an attribute to the SearchUser component.

Routing meta information

When defining a route, you can configure the meta object:

Each route object in the Routes configuration is a route record. Routing records can be nested. Therefore, when a route is matched successfully, it may match multiple routing records.

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

All routing records matched by a route are exposed as $Route objects;

Example: Iterate through the array of routing match fields and look at the META field in the record to determine whether to log in

router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { if (! auth.loggedIn()) { next({ path: '/login', query: { redirect: To.fullpath}})} else {next()}} else {next() // Make sure to call next()}})Copy the code

Transition effects


is a basic dynamic component that uses different components to jump to different routes

<! <transition :name="transitionName"> <router-view></router-view> </transition> // then in the parent component // Watch $route Determines which transition watch to use: { '$route' (to, from) { const toDepth = to.path.split('/').length const fromDepth = from.path.split('/').length this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left' } }Copy the code

Navigation guard

Vue-router provides navigation guards that are used to guard navigation by jumping or canceling. There are several opportunities for embedding route navigation: global, single route proprietary, or component level.

Remember that changes in parameters or queries do not trigger entry/exit navigational guards.

You can respond to these changes by observing the $Route object, or by using the beforeRouteUpdate component internal guard.

Global guard

Global front guard

When a navigation is triggered, the global front-guard is called in the order it was created. The guard resolves asynchronously, in which case the navigation waits until all the guards resolve.

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

Example: Often used for user authentication

router.beforeEach((to, from, next) => { if (to.name ! == 'Login' && ! isAuthenticated) next({ name: 'Login' }) else next() })Copy the code

Each guard method takes three arguments:

  • To: indicates the destination route object to be entered

  • From: The route object that the current navigation is leaving

  • Next: Execute the next method, be sure to call that method to resolve the hook; This function can pass arguments:

    • Next ()/next(true) : Next hook into the pipe; The navigation state is COMFIRMed after execution
    • Next (false) : interrupts the current route; Users can manually click the browser back button to return to the address of from
    • Next (‘/’)/next({path: ‘/’}) : jump to a specified address; The next method can pass the same arguments as $router.push()
    • next(error): Terminates navigation, error torouter.onError()

Global parsing guard

Register a global guard with router.beforeResolve. This is similar to router.beforeeach, except that the parse guard is called before the navigation is confirmed and after all the intra-component guards and asynchronous routing components are parsed.

Global post-hook

Will not accept the next function or change the navigation itself

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

Route exclusive guard

Define beforeEnter guard directly on route configuration:

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

Guards within components

Define the following route navigators directly within the routing component:

●beforeRouteEnter: before the component enters, the component instance is not created (next(VM => {})) ●beforeRouteUpdate: before the component leaves ●beforeRouteLeave: before the component leaves

const Foo = { template: `... ', beforeRouteEnter(to, from, next) {// Call the render component before the corresponding route is confirmed // no! Can!!!! Next (VM => {// access component instance through 'VM'})}, beforeRouteUpdate(to, from, next) {// In the current route change, For example, for a path /foo/:id with dynamic parameters, // will be reused since the same foo component will be rendered when it jumps between /foo/1 and /foo/2. And the hook will be called in that case. // Call beforeRouteLeave(to, from, next) {// Call beforeRouteLeave(to, from, next) {Copy the code

Data request

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

  • Retrieves after navigation: Completes navigation, then retrieves data in the following component lifecycle hooks. Display instructions such as “loading” during data retrieval.
  • Before the completion of navigation: Before the completion of navigation, data is obtained from the guard entering the route, and navigation is performed after the data is obtained successfully.

Get the data after navigation is complete

Display one loading state during data acquisition, and display different loading states between different views.

Created () {// Data is observed after the component is created, watch: {if the route changes, the method '$route' is executed again: 'fetchData' },Copy the code

Get data before navigation is complete

BeforeRouteEnter (to, from, next) {getPost(to.params.id, () => {next(vm => vm.fetchData())})}, BeforeRouteUpdate (to, from, next) {this.post = null getPost(to.params.id, () => { this.fetchData() next() }) },Copy the code

Scrolling behavior

When switching to a new path, you want the page to roll to the top, or to keep the original scrolling position, as if the page had been reloaded. Vue-router can do this, and better, by letting you customize how the page scrolls when switching routes.

Note: This feature is only available in browsers that support history.pushState.

To create a Router instance, you can provide a scrollBehavior method:

const router = new VueRouter({ routes: [...] , scrollBehavior (to, from, SavedPosition) {if (savedPosition) {return savedPosition} else {return {x: 0, y: 0}}}})Copy the code

The scrollBehavior method receives to and FROM routing objects. The third parameter savedPosition is available if and only if popState navigation (triggered by the browser’s forward/back buttons).

This method returns information about an object at the scroll position, which looks like this:

  • { x: number, y: number }
  • { selector: string, offset? : { x: number, y: number }}

Route lazy loading

JavaScript packages can become very large when packaged to build applications, affecting page loads. It would be much more efficient if we could split the components corresponding to different routes into different code blocks and then load the components only when the routes are accessed.

const Foo = () => import( './Foo.vue')
const Bar = () => import( './Bar.vue')
const Baz = () => import('./Baz.vue')
Copy the code