Vue-router 4 usage
Vue-router4 keeps most of the apis unchanged
yarn add vue-router@4
Copy the code
Create router/index.js in the SRC directory
import { createRouter, createWebHashHistory} from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
routes:[
{
path:"/".name: "home".component: () = > import('.. /views/home.vue')}],})export default router
Copy the code
Introduce the router in main.js and refer to it
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App)
.use(router)
.mount('#app')
Copy the code
Adding dynamic routes
AddRouter () dynamically appends routes during permission control
-
When receiving two parameters, the first parameter is the string of the parent route name, and the second is the object of the route record to be added
Add a new route record as a child of an existing route
-
When a parameter is accepted, the parameter is only the route record object to be added
Example Add a new route record to the route.
If a route has a name and there is already a route with the same name, it deletes the previous route first.
router.addRouter({
path: '/about'.name: 'about'.component: () = > import('./component/About.vue')
})
router.addRouter('about', {path: 'about/info'.component: () = > import('./composition/about/info.vue')})Copy the code
composition API
Navigation guard
Adds a navigation guard that is triggered when the state of a component in the current location changes. It can be used in any component. When the component is uninstalled, the navigation guard is removed.
-
OnBeforeRouteLeave () — fired when the component at the current location is about to leave
<script setup> // Click no to return false, OnBeforeRouteLeave ((to, from) => {const answer = window.confirm(' Do you want to leave the current page? ') if(! answer) { return false; } }) </script>Copy the code
-
OnBeforeRouteUpdate () — fires when the current location is about to be updated
Use the same method as onBeforeRouteLeave()
-
AfterEach () — performed afterEach navigation
router.afterEach((to, from, failure) = > { if (isNavigationFailure(failure)) { console.log('failed navigation', failure) } }) Copy the code
-
BeforeEach () – executed before any navigation
-
BeforeResolve () – Executed before the navigation is about to be parsed, in which state all components have been retrieved and other navigation guards have succeeded
router.beforeResolve(to= > { if(to.meta.requiresAuth && ! isAuthenticated)return false }) Copy the code
Routing in a
-
Router-getroutes () — Gets a complete list of all route records
-
Back () – if possible, go back through history by calling history.back(). The equivalent of the router. The go (1)
-
Forward () – If possible, advance through history by calling history.forward(). The equivalent of the router. The go (1)
-
Router.go (Number) — Allows you to move forward or backward in history
-
Router.push (path) — Programmatically navigate to a new URL by pushing an entry in the history stack
Programmatic navigation
This.$router is not available for vue3. If you need to perform some operation while performing a connection jump, you need to obtain the route instance and the route object
- UseRouter () — Returns the Router instance
- UseRoute () — Returns the current routing address
This is equivalent to using $route in the template. Must be called in setup()
<template> <! -... </button> </template> <script setup> import {useRouter, Const router = useRouter() backToHome(){router.push('/')} // Route is a responsive object that can be monitored. Const route = useRoute() watch(() => route.query, query => {console.log(query)}) </script>Copy the code
useLink()
Returns everything exposed by the V-slot API
Vue-router 4 changed
History replaces mode
This makes it easier to create routing instances and customize them
const router = createRouter({
history: createWebHashHistory(), // ← ← ← ← ← ← ←
routes: [{path: "/".name: "home".component: () = > import('./components/Home.Vue')}]})Copy the code
createWebHistory(base)
Create an HTML5 history, the most common history in single-page applications
Base for optional parameters, when the application is hosted on a site’s root folder, such as https://example.com/folder/ as very useful
createWebHistory() // Without base, the application is hosted in the root directory of the domain name https://example.com.
createWebHistory('/folder/') / / given url to https://example.com/folder/
Copy the code
createWebHashHistory(base)
Create a hash history.
This is useful for web applications that have no host (such as file://), or when the configuration server cannot handle arbitrary urls
Note: If SEO is important to you, you should use createWebHistory
Provide an optional base, which defaults to location.pathname + location.search. If there is a
// at https://example.com/folder
createWebHashHistory() / / given url to https://example.com/folder#
createWebHashHistory('/folder/') / / given url to https://example.com/folder/#
// If '#' is provided in base, it is not added to createWebHashHistory
createWebHashHistory('/folder/#/app/') / / given url to https://example.com/folder/#/app/
// You should avoid doing this because it will change the original URL and break the URL being copied
createWebHashHistory('/other-folder/') / / given url to https://example.com/other-folder/#
// at file:///usr/etc/folder/index.html
// For positions without 'host', base is ignored
createWebHashHistory('/iAmIgnored') / / url for file:///usr/etc/folder/index.html# is given
Copy the code
createMemoryHistory(base)
Create a memory-based history. The main purpose of this history is to deal with SSR. It starts in a particular place, and that place is everywhere. If the user is not in the browser context, they can replace the location with the launch location by calling router.push() or router.replace().
Base applies to all urls and defaults to ‘/’
The wildcard * is removed
All routes must now be defined using a custom regex parameter (*, /*) :
const routes = [
// pathMatch is the name of the argument, for example, jumping to /not/found
// { params: { params: { pathMatch: ['not', 'found'] }}
// This is due to the last *, which means repeated parameters if you
// It is necessary to use the unmatched path name to navigate directly to the path
{ path: '/:pathMatch(.*)*'.name: 'not-found'.component: NotFound },
// If you omit the last '*', the '/' character in the argument will be encoded during parsing or jumping
{ path: '/:pathMatch(.*)'.name: 'bad-not-found'.component: NotFound },
]
// If a named route is used, a bad example:
router.resolve({
name: 'bad-not-found'.params: { pathMatch: 'not/found' },
}).href // '/not%2Ffound'
// Good example:
router.resolve({
name: 'not-found'.params: { pathMatch: ['not'.'found'] },
}).href // '/not/found'
Copy the code
Alternative onReady isReady () ()
This method is used for the underlying server-side rendering
When the router completes the initial navigation, it returns a Promise, which means that it has resolved all the asynchronous input hooks and asynchronous components associated with the initial route. If the initial navigation has already occurred, the promise is resolved immediately. This is useful in server-side rendering to ensure that the server and client output are consistent. Note that on the server side, you need to manually push the initial location, while on the client side, the router automatically gets the initial location from the URL. When the router completes the initial navigation, it returns a Promise, which means that it has resolved all the asynchronous input hooks and asynchronous components associated with the initial route. If the initial navigation has already occurred, the promise is resolved immediately. This is useful in server-side rendering to ensure that the server and client output are consistent. Note that on the server side, you need to manually push the initial location, while on the client side, the router automatically gets the initial location from the URL.
/ / will be
router.onReady(onSuccess, onError)
/ / replace
router.isReady().then(onSuccess).catch(onError)
// or use await:
try {
await router.isReady()
/ / success
} catch (err) {
/ / an error
}
Copy the code
scrollBehavior
With front-end routing, when switching to a new route, you want the page to scroll to the top, or you want to keep the original scroll position as if you were reloading the page. Vue-router does this, and it goes even further by allowing you to customize how the page scrolls when switching routes.
When creating a Router instance, you can provide a scrollBehavior method:
const router = createRouter({
history: createWebHashHistory(),
routes: [...]. , scrollBehavior (to,from, savedPosition) {
// return the desired scrolling position}})Copy the code
The scrollBehavior function receives to and from routing objects, such as Navigation Guards. The third parameter, savedPosition, is available only if this is a popstate navigation (triggered by the browser’s back/forward buttons).
Example:
Return savedPosition, and when the Back/forward button is pressed, instead of jumping to the top of the page, the browser’s native representation will roll to the previous position
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0}}}})Copy the code
<router-view>
的 <v-slot>
Now keep-Alive and Transition must be used inside the Router-view
exposes a V-slot API that uses
components to wrap your routing components
<! -- before -->
<keep-alive>
<transition>
<router-view></router-view>
</transition>
</keep-alive>
<! -- how to write -->
<! -- Get internal components and routes from V-slot -->
<router-view v-slot="{ Component, route }">
<! -- Route attribute overbinding in meta -->
<transition :name="route.meta.transition || 'fade'" mode="out-in">
<keep-alive>
<! -- dynamically render components inside keep-alive via: IS -->
<component :is="Component" :key="route.meta.usePathKey ? route.path : undefined"/>
</keep-alive>
</transition>
</router-view>
Copy the code
Router-link removed attributes
append
Remove AppEnd — You can manually set the value to an existing path
will<router-link to="child-route" append>to relative child</router-link>replace<router-link :to="append($route.path, 'child-route')">
to relative child
</router-link>
Copy the code
You must define a global append function on the App instance:
app.config.globalProperties.append = (path, pathToAppend) = > {
return path + (path.endsWith('/')?' ' : '/') + pathToAppend
}
Copy the code
tag/event
The tag attribute is the tag that defines the rendering result of the router-link. Since the tag is no longer a tag, the click does not jump, so the event needs to be triggered
The event and tag attributes in
have now been removed. You can use the V-slot API to fully customize
:
will<router-link to="/about" tag="span" event="dblclick">About Us</router-link>replace<router-link to="/about" custom v-slot="{ navigate }">
<span @click="navigate" @keypress.enter="navigate" role="link">About Us</span>
</router-link>
Copy the code
exact
Now that the exact matching logic is simplified, the special business logic is up to the user. If you want to customize this behavior, for example, considering the hash part, you should use the V-slot API to extend
.
Route guards in mixins are ignored
Resolve to replace the match
Router. match and router.resolve have been merged into router.resolve, but the signature is slightly different
Reason: Unify multiple methods for the same purpose.
Router.resolve () returns the standardized version of the routing address. It also includes an href attribute that contains any existing base.
Remove the router. GetMatchedComponents ()
This method has been deleted, because can match the component from the router. CurrentRoute. Value. The mixed extract:
router.currentRoute.value.matched.flatMap(record= >
Object.values(record.components)
)
Copy the code
Reason: This method is only used in SSR and can be done by the user in a single row.
All navigation, including the first screen navigation, is asynchronous
All navigations, including the first one, are now asynchronous, which means that if you use a transition, you might need to wait for the route to be ready before mounting the program:
app.use(router)
router.isReady().then(() = > app.mount('#app'))
Copy the code
If the route guard exists on the first screen, you can mount it directly without waiting for it to be ready. The result is the same as vuE2
Remove the parent property of a route
The parent property has been removed from the standardized route address (object returned by this.$route and router.resolve). You can still access it through the matched array:
const parent = this.$route.matched[this.$route.matched/length - 2]
Copy the code
Cause: The existence of parent and children will cause unnecessary circular reference, and the attribute can be retrieved through matched
History. The use of the state
The Vue Router saves the information on history.state. If you have any code that calls history.pushState() manually, you should either avoid it or refactor it with router.push() and history.replacestate () :
/ / will be
history.pushState(myState, ' ', url)
/ / replace
awaitrouter.push(url) history.replaceState({ ... history.state, ... myState },' ')
Copy the code
Also, if you don’t keep the current state when calling history.replacestate (), you need to pass the current history.state:
/ / will be
history.replaceState({}, ' ', url)
/ / replace
history.replaceState(history.state, ' ', url)
Copy the code
You need to configure routes in options
Reason: Routes are designed to create routes, although you can add them later. In most cases, you need at least one route, which is typically written once per application.
createRouter({ routes: []})Copy the code
Some error handling changes
An error is reported when jumping to a non-existent named route
router.push({ name: homee})
Copy the code
Reason: Previously, the route would navigate to/but not show anything (instead of the home page). It makes more sense to throw an error because we cannot generate a valid URL for navigation
Missing required parameters will throw an exception
Jumping or resolving a named route without passing the required parameters results in an error:
// Give the following routes:
const routes = [{ path: '/users/:id'.name: 'user'.component: UserDetails }]
// Failure without the 'id' parameter
router.push({ name: 'user' })
router.resolve({ name: 'user' })
Copy the code
Name child routes that do not append/if path is empty
Give nested named routes to any empty path:
const routes = [
{
path: '/dashboard'.name: 'dashboard-parent'.component: DashboardParent
children: [{path: ' '.name: 'dashboard'.component: DashboardDefault },
{ path: 'settings'.name: 'dashboard-settings'.component: DashboardSettings },
],
},
]
Copy the code
Navigation or parsing to the named route dashboard will now result in a URL without a slash:
router.resolve({ name: 'dashboard' }).href // '/dashboard'
Copy the code
This has important side-effects with the redirect at the sub-level, as follows:
const routes = [
{
path: '/parent'.component: Parent,
children: [
// will now redirect to '/home' instead of '/parent/home'
{ path: ' '.redirect: 'home' },
{ path: 'home'.component: Home },
],
},
]
Copy the code
Note that this works if the path is /parent/, because the relative address from home to /parent/ is indeed /parent/home, but the relative address from home to /parent is /home.
Reason: This is to make the trailing slash behavior consistent: by default, all routes are allowed to use trailing slashes. You can disable it by using the strict configuration and manually adding (or not adding) slashes.
$route attribute encoding
Decoding values in params, Query, and hash are now consistent wherever navigation is started (older browsers still produce unencoded path and fullPath). The initial navigation should produce the same results as the in-app navigation.
- Path/ fullPath is no longer decoded
- The hash is decoded
- Push, resolve, and replace, string arguments, or object argument path attributes must be encoded
- Params/will be decoded
- + is not processed in query, which was previously processed as %2b. If you want to process it, you can use stringifyQuery()