introduction
Creating a single page application with Vue + Vue Router is very simple: through Vue JS, the application has been composed of components. When joining the Vue Router, map the components to the route so that the Vue Router knows where to render them.
HTML
<script src="https://unpkg.com/vue@3"></script> <script src="https://unpkg.com/vue-router@4"></script> <div id="app"> <h1>Hello App!</h1> <p> <router-link to="/">Go to Home</router-link> <router-link to="/about">Go to About</router-link> </p> <router-view></router-view> </div>
router-link
Instead of using the regular a tag, a custom component router link is used to create the link. This allows Vue Router to change the URL and handle URL generation and encoding without reloading the page.
router-view
Router view displays the components corresponding to the url. You can put it anywhere to suit your layout.
JavaScript
const Home = { template: '<div>Home</div>' } const About = { template: '<div>About</div>' } const routes = [ { path: '/', component: Home }, { path: '/about', component: About }, ] const router = VueRouter.createRouter({ history: VueRouter.createWebHashHistory(), routes, // `Routes: abbreviation for routes' }) const app = Vue.createApp({}) app.use(router) app.mount('#app')
By calling app Use (router), you can use this in any component$ Access it in the form of router and use this$ Access the current route in the form of route:
Dynamic route matching with parameters
Many times, you need to map the routes of a given matching pattern to the same component. In Vue Router, a dynamic field can be used in the path, which is called path parameter:
const User = { template: '<div>User</div>', } // These will be passed to ` createRouter` const routes = [ // Dynamic fields start with a colon { path: '/users/:id', component: User }, ]
URL s like / users/johnny and / users/jolyne now map to the same route. Path parameters are represented by colon:.
Respond to changes in routing parameters
When using routes with parameters, it should be noted that when you navigate from / users/johnny to / users/jolyne, the same component instances will be reused. Because both routes render the same component, reuse is more efficient than destroying and rebuilding. However, this also means that the component's lifecycle hook will not be invoked.
To respond to parameter changes in the same component, you can simply watch any attribute on the $route object. In this scenario, it is $route params :
const User = { template: '...', created() { this.$watch( () => this.$route.params, (toParams, previousParams) => { // Respond to routing changes } ) }, }
Matching syntax of route
Most applications will use static routes such as / about and dynamic routes such as / users/:userId, just as we saw in dynamic route matching, but Vue Router can provide more ways!
Customize regular in parameters
When defining parameters such as: userId, the following rules (such as [^ /] +) (at least one character is not /) are used internally to extract parameters from the URL. When you need to distinguish two routes according to the content of parameters, the simplest way is to add a static part to the path to distinguish them:
const routes = [ // Match / o/3549 { path: '/o/:orderId' }, // Match / books / P { path: '/p/:productName' }, ]
But in some cases, you don't want to add static / o /p parts. Since orderId is always a number and productName can be anything, you can specify a custom rule for the parameter in parentheses:
const routes = [ // /: OrderID - > match only numbers { path: '/:orderId(\\d+)' }, // /: ProductName - > match anything else { path: '/:productName' }, ]
Now, go to / 25 to match /: orderId, and other cases will match /: productName. The order of the routes array is not important!
Repeatable parameters
If you need to match a route with multiple parts, such as / first/second/third, you should mark the parameters as repeatable with * (0 or more) and + (1 or more):
const routes = [ // /: chapters - > match / one, /one/two, /one/two/three, etc { path: '/:chapters+' }, // /: chapters - > match /, / one, /one/two, /one/two/three, etc { path: '/:chapters*' }, ]
This will provide an array of parameters instead of a string, and an array needs to be passed when using named routes:
Optional parameters
Can I use? Modifiers (0 or 1) mark a parameter as optional
const routes = [ // Match / users and / users/posva { path: '/users/:userId?' }, // Match / users and / users/42 { path: '/users/:userId(\\d+)?' }, ]
It should be noted here that * technically also indicates that a parameter is optional, but? Parameters cannot be repeated.
debugging
If you want to explore how routes are converted to regular to understand why a route is not matched, or report a bug, you can use the path ranking tool. It supports sharing routes through URL s.
Nested Route
The UI of some applications consists of multiple nested components. In this case, the fragment of the URL usually corresponds to a specific nested component structure, for example:
/user/johnny/profile /user/johnny/posts +------------------+ +-----------------+ | User | | User | | +--------------+ | | +-------------+ | | | Profile | | +------------> | | Posts | | | | | | | | | | | +--------------+ | | +-------------+ | +------------------+ +-----------------+
Vue Router allows you to express this relationship using nested routing configurations.
<div id="app"> <router-view></router-view> </div> const User = { template: '<div>User {{ $route.params.id }}</div>', } // These will be passed to ` createRouter` const routes = [{ path: '/user/:id', component: User }]
The < router View > here is a top-level router view. It renders top-level route matching components. Similarly, a rendered component can also contain its own nested < router View >. If you add a < router View > in the template of the User component:
const User = { template: ` <div class="user"> <h2>User {{ $route.params.id }}</h2> <router-view></router-view> </div> `, }
To render components into this nested router view, you need to configure children in the route:
const routes = [ { path: '/user/:id', component: User, children: [ { // When / user/:id/profile matches successfully // The UserProfile will be rendered inside the User's < router View > path: 'profile', component: UserProfile, }, { // When / user/:id/posts match successfully // UserPosts will be rendered inside the User's < router View > path: 'posts', component: UserPosts, }, ], }, ]
Note that nested paths starting with / are considered root paths. This allows nesting of components without using nested URL s.
As you can see, the children configuration is just another routing array, just like the routes themselves. Therefore, you can continuously nest views according to your needs.
Programming navigation
In addition to using < router link > to create a tag to define navigation links, it can also be implemented by writing code with the help of router's instance method.
Navigate to different locations
To navigate to different URLs, use router Push method. This method will add a new record to the history stack, so when the user clicks the browser Back button, it will return to the previous URL.
When you click < router link >, this method will be called internally, so click < router link: to = "..." > It is equivalent to calling router push(...) :
The parameter of this method can be a string path or an object describing the address.
// String path router.push('/users/eduardo') // Object with path router.push({ path: '/users/eduardo' }) // Name the route and add parameters to let the route establish the url router.push({ name: 'user', params: { username: 'eduardo' } }) // With query parameters, the result is / register?plan=private router.push({ path: '/register', query: { plan: 'private' } }) // With hash, the result is / about#team router.push({ path: '/about', hash: '#team' })
If path is provided, params will be ignored. This is not the case with the above query. Instead, you need to provide the name of the route or handwritten complete path with parameters:
const username = 'eduardo' // You can create the url manually, but you must handle the encoding yourself router.push(`/user/${username}`) // -> /user/eduardo // same router.push({ path: `/user/${username}` }) // -> /user/eduardo // If possible, use 'name' and 'params' to benefit from automatic URL encoding router.push({ name: 'user', params: { username } }) // -> /user/eduardo // `params' cannot be used with 'path' router.push({ path: '/user', params: { username } }) // -> /user
Due to the attribute to and router Push accepts the same kind of objects, so the rules of the two are exactly the same.
router.push and all other navigation methods will return a Promise, so that we can wait until the navigation is completed to know whether it is successful or failed.
Replace current position
Its function is similar to router Push, the only difference is that it does not add new records to history when navigating, as its name implies - it replaces the current entry.
It can also be passed directly to router Add an attribute replace: true in routeLocation of push:
router.push({ path: '/home', replace: true }) // amount to router.replace({ path: '/home' })