From: skirtle <65301168+skirtles-code@users.noreply.github.com>
Date: Thu, 14 Mar 2024 06:34:10 +0000 (+0000)
Subject: docs: update examples to use SFCs (#2174)
X-Git-Tag: v4.3.1~13
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cadcc47468b3d0da0d87e4ab0620e9b859875e47;p=thirdparty%2Fvuejs%2Frouter.git
docs: update examples to use SFCs (#2174)
* docs: update examples to use SFCs
* Further small docs tweaks
---
diff --git a/packages/docs/guide/advanced/composition-api.md b/packages/docs/guide/advanced/composition-api.md
index 3e9213f7..3a4fc64a 100644
--- a/packages/docs/guide/advanced/composition-api.md
+++ b/packages/docs/guide/advanced/composition-api.md
@@ -2,90 +2,84 @@
-The introduction of `setup` and Vue's [Composition API](https://vuejs.org/guide/extras/composition-api-faq.html), open up new possibilities but to be able to get the full potential out of Vue Router, we will need to use a few new functions to replace access to `this` and in-component navigation guards.
+The introduction of Vue's [Composition API](https://vuejs.org/guide/extras/composition-api-faq.html) opened up new possibilities, but to be able to get the full potential out of Vue Router, we will need to use a few new functions to replace access to `this` and in-component navigation guards.
## Accessing the Router and current Route inside `setup`
-Because we don't have access to `this` inside of `setup`, we cannot directly access `this.$router` or `this.$route` anymore. Instead we use the `useRouter` and `useRoute` functions:
+Because we don't have access to `this` inside of `setup`, we cannot directly access `this.$router` or `this.$route`. Instead, we use the `useRouter` and `useRoute` composables:
-```js
+```vue
+
```
-The `route` object is a reactive object, so any of its properties can be watched and you should **avoid watching the whole `route`** object. In most scenarios, you should directly watch the param you are expecting to change
+The `route` object is a reactive object. In most scenarios, you should **avoid watching the whole `route`** object. Instead, you can directly watch the properties you are expecting to change:
-```js
+```vue
+
```
-Note we still have access to `$router` and `$route` in templates, so there is no need to return `router` or `route` inside of `setup`.
+Note we still have access to `$router` and `$route` in templates, so there's no need to use `useRouter` or `useRoute` if we only need those object in the template.
## Navigation Guards
-While you can still use in-component navigation guards with a `setup` function, Vue Router exposes update and leave guards as Composition API functions:
+Vue Router exposes update and leave guards as Composition API functions:
-```js
+```vue
+
```
Composition API guards can also be used in any component rendered by ``, they don't have to be used directly on the route component like in-component guards.
@@ -94,40 +88,34 @@ Composition API guards can also be used in any component rendered by `
import { RouterLink, useLink } from 'vue-router'
import { computed } from 'vue'
-export default {
- name: 'AppLink',
-
- props: {
- // add @ts-ignore if using TypeScript
- ...RouterLink.props,
- inactiveClass: String,
- },
-
- setup(props) {
- const {
- // the resolved route object
- route,
- // the href to use in a link
- href,
- // boolean ref indicating if the link is active
- isActive,
- // boolean ref indicating if the link is exactly active
- isExactActive,
- // function to navigate to the link
- navigate
- } = useLink(props)
-
- const isExternalLink = computed(
- () => typeof props.to === 'string' && props.to.startsWith('http')
- )
-
- return { isExternalLink, href, navigate, isActive }
- },
-}
+const props = defineProps({
+ // add @ts-ignore if using TypeScript
+ ...RouterLink.props,
+ inactiveClass: String,
+})
+
+const {
+ // the resolved route object
+ route,
+ // the href to use in a link
+ href,
+ // boolean ref indicating if the link is active
+ isActive,
+ // boolean ref indicating if the link is exactly active
+ isExactActive,
+ // function to navigate to the link
+ navigate
+} = useLink(props)
+
+const isExternalLink = computed(
+ () => typeof props.to === 'string' && props.to.startsWith('http')
+)
+
```
Note that the RouterLink's `v-slot` gives access to the same properties as the `useLink` composable.
diff --git a/packages/docs/guide/advanced/data-fetching.md b/packages/docs/guide/advanced/data-fetching.md
index e0725abe..c6fd1bfb 100644
--- a/packages/docs/guide/advanced/data-fetching.md
+++ b/packages/docs/guide/advanced/data-fetching.md
@@ -10,11 +10,13 @@ Technically, both are valid choices - it ultimately depends on the user experien
## Fetching After Navigation
-When using this approach, we navigate and render the incoming component immediately, and fetch data in the component's `created` hook. It gives us the opportunity to display a loading state while the data is being fetched over the network, and we can also handle loading differently for each view.
+When using this approach, we navigate and render the incoming component immediately, and fetch data in the component itself. It gives us the opportunity to display a loading state while the data is being fetched over the network, and we can also handle loading differently for each view.
-Let's assume we have a `Post` component that needs to fetch the data for a post based on `$route.params.id`:
+Let's assume we have a `Post` component that needs to fetch the data for a post based on `route.params.id`:
-```html
+::: code-group
+
+```vue [Composition API]
Loading...
@@ -27,9 +29,54 @@ Let's assume we have a `Post` component that needs to fetch the data for a post
+
+
```
-```js
+```vue [Options API]
+
+
+
Loading...
+
+
{{ error }}
+
+
+
{{ post.title }}
+
{{ post.body }}
+
+
+
+
+
```
+:::
+
## Fetching Before Navigation
-With this approach we fetch the data before actually navigating to the new
-route. We can perform the data fetching in the `beforeRouteEnter` guard in the incoming component, and only call `next` when the fetch is complete. The callback passed to `next` will be called **after the component is mounted**:
+With this approach we fetch the data before actually navigating to the new route. We can perform the data fetching in the `beforeRouteEnter` guard in the incoming component, and only call `next` when the fetch is complete. The callback passed to `next` will be called **after the component is mounted**:
```js
export default {
@@ -81,29 +128,28 @@ export default {
error: null,
}
},
- beforeRouteEnter(to, from, next) {
- getPost(to.params.id, (err, post) => {
- // `setData` is a method defined below
- next(vm => vm.setData(err, post))
- })
+ async beforeRouteEnter(to, from, next) {
+ try {
+ const post = await getPost(to.params.id)
+ // `setPost` is a method defined below
+ next(vm => vm.setPost(post))
+ } catch (err) {
+ // `setError` is a method defined below
+ next(vm => vm.setError(err))
+ }
},
// when route changes and this component is already rendered,
// the logic will be slightly different.
- async beforeRouteUpdate(to, from) {
+ beforeRouteUpdate(to, from) {
this.post = null
- try {
- this.post = await getPost(to.params.id)
- } catch (error) {
- this.error = error.toString()
- }
+ getPost(to.params.id).then(this.setPost).catch(this.setError)
},
methods: {
- setData(error, post) {
- if (error) {
- this.error = error
- } else {
- this.post = post
- }
+ setPost(post) {
+ this.post = post
+ },
+ setError(err) {
+ this.error = err.toString()
}
}
}
diff --git a/packages/docs/guide/advanced/dynamic-routing.md b/packages/docs/guide/advanced/dynamic-routing.md
index a2ad81a7..d8d83b79 100644
--- a/packages/docs/guide/advanced/dynamic-routing.md
+++ b/packages/docs/guide/advanced/dynamic-routing.md
@@ -30,7 +30,7 @@ The page will still show the `Article` component, we need to manually call `rout
```js
router.addRoute({ path: '/about', component: About })
-// we could also use this.$route or route = useRoute() (inside a setup)
+// we could also use this.$route or useRoute()
router.replace(router.currentRoute.value.fullPath)
```
diff --git a/packages/docs/guide/advanced/extending-router-link.md b/packages/docs/guide/advanced/extending-router-link.md
index 6b4ff25c..5102b9ad 100644
--- a/packages/docs/guide/advanced/extending-router-link.md
+++ b/packages/docs/guide/advanced/extending-router-link.md
@@ -9,7 +9,28 @@ The RouterLink component exposes enough `props` to suffice most basic applicatio
Let's extend RouterLink to handle external links as well and adding a custom `inactive-class` in an `AppLink.vue` file:
-```vue
+::: code-group
+
+```vue [Composition API]
+
+
@@ -30,7 +51,9 @@ Let's extend RouterLink to handle external links as well and adding a custom `in
+```
+```vue [Options API]
+
+
+
+
+
+
+
+
+
+
+
```
+:::
+
If you prefer using a render function or create `computed` properties, you can use the `useLink` from the [Composition API](./composition-api.md):
```js
diff --git a/packages/docs/guide/advanced/meta.md b/packages/docs/guide/advanced/meta.md
index 7c5f045d..321158ff 100644
--- a/packages/docs/guide/advanced/meta.md
+++ b/packages/docs/guide/advanced/meta.md
@@ -38,7 +38,7 @@ First, each route object in the `routes` configuration is called a **route recor
For example, with the above route config, the URL `/posts/new` will match both the parent route record (`path: '/posts'`) and the child route record (`path: 'new'`).
-All route records matched by a route are exposed on the `$route` object (and also route objects in navigation guards) as the `$route.matched` Array. We could loop through that array to check all `meta` fields, but Vue Router also provides you a `$route.meta` that is a non-recursive merge of **all `meta`** fields from parent to child. Meaning you can simply write
+All route records matched by a route are exposed on the `route` object (and also route objects in navigation guards) as the `route.matched` Array. We could loop through that array to check all `meta` fields, but Vue Router also provides you a `route.meta` that is a non-recursive merge of **all `meta`** fields from parent to child. Meaning you can simply write:
```js
router.beforeEach((to, from) => {
diff --git a/packages/docs/guide/advanced/navigation-guards.md b/packages/docs/guide/advanced/navigation-guards.md
index 57884d3c..059328d3 100644
--- a/packages/docs/guide/advanced/navigation-guards.md
+++ b/packages/docs/guide/advanced/navigation-guards.md
@@ -224,7 +224,7 @@ It is possible to achieve similar behavior to per-route guards by using [route m
Finally, you can directly define route navigation guards inside route components (the ones passed to the router configuration)
-### Using the options API
+### Using the Options API
You can add the following options to route components:
@@ -232,9 +232,9 @@ You can add the following options to route components:
- `beforeRouteUpdate`
- `beforeRouteLeave`
-```js
-const UserDetails = {
- template: `...`,
+```vue
+
```
The `beforeRouteEnter` guard does **NOT** have access to `this`, because the guard is called before the navigation is confirmed, thus the new entering component has not even been created yet.
@@ -283,9 +284,9 @@ beforeRouteLeave (to, from) {
}
```
-### Using the composition API
+### Using the Composition API
-If you are writing your component using the [composition API and a `setup` function](https://vuejs.org/api/composition-api-setup.html), you can add update and leave guards through `onBeforeRouteUpdate` and `onBeforeRouteLeave` respectively. Please refer to the [Composition API section](./composition-api.md#navigation-guards) for more details.
+If you are writing your component using the Composition API, you can add update and leave guards through `onBeforeRouteUpdate` and `onBeforeRouteLeave` respectively. Please refer to the [Composition API section](./composition-api.md#navigation-guards) for more details.
## The Full Navigation Resolution Flow
diff --git a/packages/docs/guide/essentials/dynamic-matching.md b/packages/docs/guide/essentials/dynamic-matching.md
index f74ab649..634dd158 100644
--- a/packages/docs/guide/essentials/dynamic-matching.md
+++ b/packages/docs/guide/essentials/dynamic-matching.md
@@ -8,9 +8,7 @@
Very often we will need to map routes with the given pattern to the same component. For example, we may have a `User` component which should be rendered for all users but with different user IDs. In Vue Router we can use a dynamic segment in the path to achieve that, we call that a _param_:
```js
-const User = {
- template: '
User
',
-}
+import User from './User.vue'
// these are passed to `createRouter`
const routes = [
@@ -21,22 +19,25 @@ const routes = [
Now URLs like `/users/johnny` and `/users/jolyne` will both map to the same route.
-A _param_ is denoted by a colon `:`. When a route is matched, the value of its _params_ will be exposed as `this.$route.params` in every component. Therefore, we can render the current user ID by updating `User`'s template to this:
+A _param_ is denoted by a colon `:`. When a route is matched, the value of its _params_ will be exposed as `route.params` in every component. Therefore, we can render the current user ID by updating `User`'s template to this:
-```js
-const User = {
- template: '
User {{ $route.params.id }}
',
-}
+```vue
+
+
+
+ User {{ $route.params.id }}
+
+
```
-You can have multiple _params_ in the same route, and they will map to corresponding fields on `$route.params`. Examples:
+You can have multiple _params_ in the same route, and they will map to corresponding fields on `route.params`. Examples:
-| pattern | matched path | \$route.params |
-| ------------------------------ | ------------------------ | ---------------------------------------- |
-| /users/:username | /users/eduardo | `{ username: 'eduardo' }` |
+| pattern | matched path | route.params |
+| ------------------------------ | ------------------------ | -------------------------------------- |
+| /users/:username | /users/eduardo | `{ username: 'eduardo' }` |
| /users/:username/posts/:postId | /users/eduardo/posts/123 | `{ username: 'eduardo', postId: '123' }` |
-In addition to `$route.params`, the `$route` object also exposes other useful information such as `$route.query` (if there is a query in the URL), `$route.hash`, etc. You can check out the full details in the [API Reference](../../api/interfaces/RouteLocationNormalized.md).
+In addition to `route.params`, the `route` object also exposes other useful information such as `route.query` (if there is a query in the URL), `route.hash`, etc. You can check out the full details in the [API Reference](../../api/interfaces/RouteLocationNormalized.md).
A working demo of this example can be found [here](https://codesandbox.io/s/route-params-vue-router-examples-mlb14?from-embed&initialpath=%2Fusers%2Feduardo%2Fposts%2F1).
@@ -57,34 +58,70 @@ A working demo of this example can be found [here](https://codesandbox.io/s/rout
One thing to note when using routes with params is that when the user navigates from `/users/johnny` to `/users/jolyne`, **the same component instance will be reused**. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. **However, this also means that the lifecycle hooks of the component will not be called**.
-To react to params changes in the same component, you can simply watch anything on the `$route` object, in this scenario, the `$route.params`:
+To react to params changes in the same component, you can simply watch anything on the `route` object, in this scenario, the `route.params`:
-```js
-const User = {
- template: '...',
+::: code-group
+
+```vue [Composition API]
+
+```
+
+```vue [Options API]
+
```
+:::
+
Or, use the `beforeRouteUpdate` [navigation guard](../advanced/navigation-guards.md), which also allows to cancel the navigation:
-```js
-const User = {
- template: '...',
+::: code-group
+
+```vue [Composition API]
+
+```
+
+```vue [Options API]
+
```
+:::
+
## Catch all / 404 Not found Route
-
-
+
+
+
```
A view is rendered by using a component, therefore multiple views require
diff --git a/packages/docs/guide/essentials/nested-routes.md b/packages/docs/guide/essentials/nested-routes.md
index fd3764b1..ba2f490e 100644
--- a/packages/docs/guide/essentials/nested-routes.md
+++ b/packages/docs/guide/essentials/nested-routes.md
@@ -22,16 +22,24 @@ With Vue Router, you can express this relationship using nested route configurat
Given the app we created in the last chapter:
-```html
-
-
-
+```vue
+
+
+
+
+```
+
+```vue
+
+
+
+ User {{ $route.params.id }}
+
+
```
```js
-const User = {
- template: '
User {{ $route.params.id }}
',
-}
+import User from './User.vue'
// these are passed to `createRouter`
const routes = [{ path: '/user/:id', component: User }]
@@ -39,15 +47,14 @@ const routes = [{ path: '/user/:id', component: User }]
The `` here is a top-level `router-view`. It renders the component matched by a top level route. Similarly, a rendered component can also contain its own, nested ``. For example, if we add one inside the `User` component's template:
-```js
-const User = {
- template: `
-
-
User {{ $route.params.id }}
-
-
- `,
-}
+```vue
+
+
+
+
User {{ $route.params.id }}
+
+
+
```
To render components into this nested `router-view`, we need to use the `children` option in any of the routes:
diff --git a/packages/docs/guide/essentials/passing-props.md b/packages/docs/guide/essentials/passing-props.md
index 65bfb85b..e5d9f675 100644
--- a/packages/docs/guide/essentials/passing-props.md
+++ b/packages/docs/guide/essentials/passing-props.md
@@ -5,26 +5,74 @@
title="Learn how to pass props to route components"
/>
-Using `$route` in your component creates a tight coupling with the route which limits the flexibility of the component as it can only be used on certain URLs. While this is not necessarily a bad thing, we can decouple this behavior with a `props` option:
+Using `$route` or `useRoute()` in your component creates a tight coupling with the route which limits the flexibility of the component as it can only be used on certain URLs. While this is not necessarily a bad thing, we can decouple this behavior with a `props` option.
-We can replace
+Let's return to our earlier example:
+
+```vue
+
+
+
'
+import User from './User.vue'
+
+// these are passed to `createRouter`
+const routes = [
+ { path: '/users/:id', component: User },
+]
+```
+
+We can remove the direct dependency on `$route` in `User.vue` by declaring a prop instead:
+
+::: code-group
+
+```vue [Composition API]
+
+
+
+
+
+ User {{ id }}
+
+
+```
+
+```vue [Options API]
+
+
+
+
+
+ User {{ id }}
+
+
```
-with
+:::
+
+We can then configure the route to pass the `id` param as a prop by setting `props: true`:
```js
-const User = {
- // make sure to add a prop named exactly like the route param
- props: ['id'],
- template: '
User {{ id }}
'
-}
-const routes = [{ path: '/user/:id', component: User, props: true }]
+const routes = [
+ { path: '/user/:id', component: User, props: true }
+]
```
This allows you to use the component anywhere, which makes the component easier to reuse and test.
diff --git a/packages/docs/guide/index.md b/packages/docs/guide/index.md
index 3ba003da..3b31648b 100644
--- a/packages/docs/guide/index.md
+++ b/packages/docs/guide/index.md
@@ -4,100 +4,202 @@
href="https://vueschool.io/courses/vue-router-4-for-everyone"
title="Learn how to build powerful Single Page Applications with the Vue Router on Vue School">Watch a Free Vue Router Video Course
-Creating a Single-page Application with Vue + Vue Router feels natural: with Vue.js, we are already composing our application with components. When adding Vue Router to the mix, all we need to do is map our components to the routes and let Vue Router know where to render them. Here's a basic example:
+Vue Router is the official client-side routing solution for Vue.
-## HTML
+Client-side routing is used by single-page applications (SPAs) to tie the browser URL to the content seen by the user. As users navigate around the application, the URL updates accordingly, but the page doesn't need to be reloaded from the server.
-```html
-
-
+Vue Router is built on Vue's component system. You configure **routes** to tell Vue Router which components to show for each URL path.
-
+::: tip Prerequisites
+This guide will assume that you are already familiar with Vue itself. You don't need to be a Vue expert, but you may occasionally need to refer back to [the core Vue documentation](https://vuejs.org/) for more information about certain features.
+:::
+
+## An example
+
+To introduce some of the main ideas, we're going to consider this example:
+
+- [Vue Playground example](https://play.vuejs.org/#eNqFVVtv2zYU/itn6gArmC05btEHTXXTFcWyYZeiLfYy7UGWji02EsmRlOPA8H/fIambnaRD4Fg61++c7yN9DJqc8eirDpKANVIoA0coFOYG30kJJ9gq0cBs3+Is412AEq1B1Xmi2L+ObpvX+3IpI5+b8aFqSJ+rjANErcbQp/v3RrTchLMXlDa7CuZBl07YUoONrCl/bQPT6np9i3UtbLPv0phenVm6L3rQRgm+W79vlULeIQaZmypJ484HxyN87xzRtq3rj+SE08mViX2dlOf7vuAnh/I3xu/AiDdZEGfB+mdBz3ArGkzj0f9sRr4hy5D2zr49ykvjvmdqeTmv9RfDe4i7uM6dxsNiaF9+l0+y+Ts2Qj3cMm3oa94Zfd0py4uBzYFPO6Br3ZPaGzpme9rtQGdxg2WUgOC6Y0PDG/jbjnL0vMAsnhEsQcU4UZaMbU/z8zC3x/PYsbcN/ueilaJW03nDoy1Y+VUkT+0nvHI9PVB6PJE8M44HN2iJ27yt+9q09ek+rFR1oZg0RM5FgmvboKlEqRP/BrATX4SDH171JgBD4CIvThXJVldhP7Y7J9DtxP4nxZKk+470cnFQVuseHh2TlTduWmMEh5uiZsUdSXPAcKlOH/hIZmfEjhODRtPaozNKjyiiGcqn75Ej0Pl3lMyHp2fFeMHnEB/SRia+ict6ep/GXBWV1UGHyGtgh5O1K0KvuC8T/duieoi6tLdvYUYg+rXTmKH3jLmeKoW0owLDI7h8IrnvfAKrIargxfQ/lA0LHjmr8w3W3X3w2dVMIGWchoH9ohEl1pFRrCE2fccsgCY/1Mh3piLjaknc+pujr3TOqedk0eSSrg/BiVU3WtY5dBYMks2CkRtrzoLKGKmTOG65vNtFtON4jLh5Fb2MlnFJJ2tijVA3i40S99rdV1ngNmtr31BQXOLeCFHrRS7Zcy0eBd68jl5H13HNNjFVjxkv8eBq94unMY0mQWzZ7mJIKwtWo/pTGkaCORs2p9+Z+1+dzagWB6BFhcXdE/av+uAhf1RI0+1xMpzJFWnOuz98/gMP9Dw4icW2puhvOD+hFnVrMfqwn1peEuxJnEP7i+OM8d0X/eFgkOt+KAt0FLIj8v03Rh/hvoxeTbaozUONOiq0/aGhX6w5aY1xn7cRqkSVwEoegMCyEl4sl8sf3d1H5RhfbATdKk0C10t5cHaZlyWBHSzUJeNUFtaQww/08Tenz65xSzf+NLJaTTuP5UcARVFMACSwpL9VVyE4/QesCg/V)
+
+Let's start by looking at the root component, `App.vue`.
+
+### App.vue
+
+```vue
+
Hello App!
-
-
-
-
- Go to Home
- Go to About
+ Current route path: {{ $route.fullPath }}