]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
docs(migration): reorder
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 7 Oct 2020 16:08:23 +0000 (18:08 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Wed, 7 Oct 2020 16:08:23 +0000 (18:08 +0200)
docs/guide/migration/index.md

index 4e78d4d8141c8bfeb40b9b480dd13664aed0dac0..9112d54188bfc7897f2fc088186aef4b62e3c627 100644 (file)
 
 Most of Vue Router API has remained unchanged during its rewrite from v3 (for Vue 2) to v4 (for Vue 3) but there are still a few breaking changes that you might encounter while migrating your application. This guide is here to help you understand why these changes happened and how to adapt your application to make it work with Vue Router 4.
 
-## New Features
-
-Some of new features to keep an eye on in Vue Router 4 include:
-
-- [Dynamic Routing](/api/#addroute-2)
-- [Composition API](/guide/advanced/composition-api.md)
-<!-- - Custom History implementation -->
-
-## Breaking Changes: Improvements
-
-The following changes should not be a problem for you but they are technically breaking changes that will show a different behavior and might break parts of your application.
-
-### Non existent named routes
-
-Pushing or resolving a non existent named route throws an error:
-
-```js
-// Oops, we made a typo in name
-router.push({ name: 'homee' }) // throws
-router.resolve({ name: 'homee' }) // throws
-```
-
-**Reason**: Previously, the router would navigate to `/` but display nothing (instead of the home page). Throwing an error makes more sense because we cannot produce a valid URL to navigate to.
-
-### Missing required `params` on named routes
-
-Pushing or resolving a named route without its required params will throw an error:
-
-```js
-// given the following route:
-const routes = [{ path: '/users/:id', name: 'user', component: UserDetails }]
-
-// Missing the `id` param will fail
-router.push({ name: 'user' })
-router.resolve({ name: 'user' })
-```
+## Breaking Changes
 
-**Reason**: Same as above.
+Changes are ordered by their usage. It is therefore recommended to follow this list in order.
 
-### Named children routes with an empty `path` no longer appends a slash
+### new Router becomes createRouter
 
-Given any nested named route with an empty `path`:
+Vue Router is no longer a class but a set of functions. Instead of writing `new Router()`, you now have to call `createRouter`:
 
 ```js
-const routes = [
-  {
-    path: '/dashboard',
-    name: 'dashboard-parent',
-    component: DashboardParent
-    children: [
-      { path: '', name: 'dashboard', component: DashboardDefault },
-      { path: 'settings', name: 'dashboard-settings', component: DashboardSettings },
-    ],
-  },
-]
-```
+// previously was
+// import Router from 'vue-router'
+import { createRouter } from 'vue-router'
 
-Navigating or resolving to the named route `dashboard` will now produce a URL **without a trailing slash**:
-
-```js
-router.resolve({ name: 'dashboard' }).href // '/dashboard'
-```
-
-This has an important side effect about children `redirect` records like these:
-
-```js
-const routes = [
-  {
-    path: '/parent',
-    component: Parent,
-    children: [
-      // this would now redirect to `/home` instead of `/parent/home`
-      { path: '', redirect: 'home' },
-      { path: 'home', component: Home },
-    ],
-  },
-]
+const router = createRouter({
+  // ...
+})
 ```
 
-Note this will work if `path` was `/parent/` as the relative location `home` to `/parent/` is indeed `/parent/home` but the relative location of `home` to `/parent` is `/home`.
-
-<!-- Learn more about relative links [in the cookbook](/cookbook/relative-links.md). -->
-
-**Reason**: This is to make trailing slash behavior consistent: by default all routes allow a trailing slash. It can be disabled by using the `strict` option and manually appending (or not) a slash to the routes.
-
-<!-- TODO: maybe a cookbook entry -->
-
-### `$route` properties Encoding
-
-Decoded values in `params`, `query`, and `hash` are now consistent no matter where the navigation is initiated (older browsers will still produce unencoded `path` and `fullPath`). The initial navigation should yield the same results as in-app navigations.
-
-Given any [normalized route location](/api/#routelocationnormalized):
-
-- Values in `path`, `fullPath` are not decoded anymore. They will appear as provided by the browser (most browsers provide them encoded). e.g. directly writing on the address bar `https://example.com/hello world` will yield the encoded version: `https://example.com/hello%20world` and both `path` and `fullPath` will be `/hello%20world`.
-- `hash` is now decoded, that way it can be copied over: `router.push({ hash: $route.hash })` and be used directly in [scrollBehavior](/api/#scrollbehavior)'s `el` option.
-- When using `push`, `resolve`, and `replace` and providing a `string` location or a `path` property in an object, **it must be encoded** (like in the previous version). On the other hand, `params`, `query` and `hash` must be provided in its unencoded version.
-- The slash character (`/`) is now properly decoded inside `params` while still producing an encoded version on the URL: `%2F`.
-- The `+` character (`%2B` in its encoded form) no longer receives special treatment when found on the query section of the URL. It used to be encoded to deal with [legacy systems using `application/x-www-form-urlencoded`](https://url.spec.whatwg.org/#urlencoded-parsing). This can still be customized when providing custom [parsing and stringifying for `query`](/api/#stringifyquery) because they are responsible of encoding and decoding query params.
-
-**Reason**: This allows to easily copy existing properties of a location when calling `router.push()` and `router.resolve()`, and make the resulting route location consistent across browsers. `router.push()` is now idempotent, meaning that calling `router.push(route.fullPath)`, `router.push({ hash: route.hash })`, `router.push({ query: route.query })`, and `router.push({ params: route.params })` will not create extra encoding.
-
-## Breaking Changes: API Changes
+### New `history` option to replace `mode`
 
-The following changes will require you to adapt your code
+The `mode: 'history'` option has been replaced with a more flexible one named `history`. Depending on which mode you were using, you will have to replace it with the appropriate function:
 
-### New `history` option to replace `mode`
+- `"history"`: `createWebHistory()`
+- `"hash"`: `createWebHashHistory()`
+- `"abstract"`: `createMemoryHistory()`
 
-The `mode: 'history'` option has been replaced with a more flexible one named `history`:
+Here is a full snippet:
 
 ```js
 import { createRouter, createWebHistory } from 'vue-router'
@@ -198,25 +117,27 @@ try {
 }
 ```
 
-**Reason**: As Promises become available in all major browsers, we try to natively integrate them in Vue Router's API.
-
-### Removal of `router.match` and changes to `router.resolve`
+### `scrollBehavior` changes
 
-Both `router.match`, and `router.resolve` have been merged together into `router.resolve` with a slightly different signature. [Refer to the API](/api/#resolve) for more details.
+The object returned in `scrollBehavior` is now similar to [`ScrollToOptions`](https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions): `x` is renamed to `left` and `y` is renamed to `top`. See [RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0035-router-scroll-position.md).
 
-**Reason**: Uniting multiple methods that were used for the same purpose.
+**Reason**: making the object similar to `ScrollToOptions` to make it feel more familiar with native JS APIs and potentially enable future new options.
 
-### Removal of `router.getMatchedComponents()`
+### `<router-view>`, `<keep-alive>`, and `<transition>`
 
-The method `router.getMatchedComponents` is now removed as matched components can be retrieved from `router.currentRoute.value.matched`:
+`transition` and `keep-alive` must now be used **inside** of `RouterView` via the `v-slot` API:
 
-```js
-router.currentRoute.value.matched.flatMap(record =>
-  Object.values(record.components)
-)
+```vue
+<router-view v-slot="{ Component }">
+  <transition>
+    <keep-alive>
+      <component :is="Component" />
+    </keep-alive>
+  </transition>
+</router-view>
 ```
 
-**Reason**: This method was only used during SSR and is a one liner that can be done by the user.
+**Reason**: This is was a necessary change. See the [related RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0034-router-view-keep-alive-transitions.md).
 
 ### Removal of `append` prop in `<router-link>`
 
@@ -249,7 +170,7 @@ replace
 <router-link to="/about" tag="span" event="dblclick">About Us</router-link>
 with
 <router-link to="/about" custom v-slot="{ navigate }">
-  <span @dblclick="navigate" role="link">About Us</span>
+  <span @click="navigate" @keypress.enter="navigate" role="link">About Us</span>
 </router-link>
 ```
 
@@ -259,6 +180,30 @@ with
 
 The `exact` prop has been removed because the caveat it was fixing is no longer present. See the [RFC about active matching](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0028-router-active-link.md) changes for more details.
 
+**Reason**: As Promises become available in all major browsers, we try to natively integrate them in Vue Router's API.
+
+### Navigation guards in mixins are ignored
+
+At the moment navigation guards in mixins are not supported. You can track its support at [vue-router#454](https://github.com/vuejs/vue-router-next/issues/454).
+
+### Removal of `router.match` and changes to `router.resolve`
+
+Both `router.match`, and `router.resolve` have been merged together into `router.resolve` with a slightly different signature. [Refer to the API](/api/#resolve) for more details.
+
+**Reason**: Uniting multiple methods that were used for the same purpose.
+
+### Removal of `router.getMatchedComponents()`
+
+The method `router.getMatchedComponents` is now removed as matched components can be retrieved from `router.currentRoute.value.matched`:
+
+```js
+router.currentRoute.value.matched.flatMap(record =>
+  Object.values(record.components)
+)
+```
+
+**Reason**: This method was only used during SSR and is a one liner that can be done by the user.
+
 ### **All** navigations are now always asynchronous
 
 All navigations, including the first one, are now asynchronous, meaning that, if you use a `transition`, you may need to wait for the router to be _ready_ before mounting the app:
@@ -273,28 +218,6 @@ Otherwise there will be an initial transition as if you provided the `appear` pr
 
 Note that **if you have navigation guards upon the initial navigation**, you might not want to block the app render until they are resolved unless you are doing Server Side Rendering. In this scenario, not waiting the router to be ready to mount the app would yield the same result as in Vue 2.
 
-### `scrollBehavior` changes
-
-The object returned in `scrollBehavior` is now similar to [`ScrollToOptions`](https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions): `x` is renamed to `left` and `y` is renamed to `top`. See [RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0035-router-scroll-position.md).
-
-**Reason**: making the object similar to `ScrollToOptions` to make it feel more familiar with native JS APIs and potentially enable future new options.
-
-### `<router-view>`, `<keep-alive>`, and `<transition>`
-
-`transition` and `keep-alive` must now be used **inside** of `RouterView` via the `v-slot` API:
-
-```vue
-<router-view v-slot="{ Component }">
-  <transition>
-    <keep-alive>
-      <component :is="Component" />
-    </keep-alive>
-  </transition>
-</router-view>
-```
-
-**Reason**: This is was a necessary change. See the [related RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0034-router-view-keep-alive-transitions.md).
-
 ### Passing content to route components' `<slot>`
 
 Before you could directly pass a template to be rendered by a route components' `<slot>` by nesting it under a `<router-view>` component:
@@ -362,11 +285,96 @@ createRouter({ routes: [] })
 
 **Reason**: The router is designed to be created with routes even though you can add them later on. You need at least one route in most scenarios and this is written once per app in general.
 
-### Navigation guards in mixins are ignored
+### Non existent named routes
 
-At the moment navigation guards in mixins are not supported. You can track its support at [vue-router#454](https://github.com/vuejs/vue-router-next/issues/454).
+Pushing or resolving a non existent named route throws an error:
 
-### TypeScript
+```js
+// Oops, we made a typo in name
+router.push({ name: 'homee' }) // throws
+router.resolve({ name: 'homee' }) // throws
+```
+
+**Reason**: Previously, the router would navigate to `/` but display nothing (instead of the home page). Throwing an error makes more sense because we cannot produce a valid URL to navigate to.
+
+### Missing required `params` on named routes
+
+Pushing or resolving a named route without its required params will throw an error:
+
+```js
+// given the following route:
+const routes = [{ path: '/users/:id', name: 'user', component: UserDetails }]
+
+// Missing the `id` param will fail
+router.push({ name: 'user' })
+router.resolve({ name: 'user' })
+```
+
+**Reason**: Same as above.
+
+### Named children routes with an empty `path` no longer appends a slash
+
+Given any nested named route with an empty `path`:
+
+```js
+const routes = [
+  {
+    path: '/dashboard',
+    name: 'dashboard-parent',
+    component: DashboardParent
+    children: [
+      { path: '', name: 'dashboard', component: DashboardDefault },
+      { path: 'settings', name: 'dashboard-settings', component: DashboardSettings },
+    ],
+  },
+]
+```
+
+Navigating or resolving to the named route `dashboard` will now produce a URL **without a trailing slash**:
+
+```js
+router.resolve({ name: 'dashboard' }).href // '/dashboard'
+```
+
+This has an important side effect about children `redirect` records like these:
+
+```js
+const routes = [
+  {
+    path: '/parent',
+    component: Parent,
+    children: [
+      // this would now redirect to `/home` instead of `/parent/home`
+      { path: '', redirect: 'home' },
+      { path: 'home', component: Home },
+    ],
+  },
+]
+```
+
+Note this will work if `path` was `/parent/` as the relative location `home` to `/parent/` is indeed `/parent/home` but the relative location of `home` to `/parent` is `/home`.
+
+<!-- Learn more about relative links [in the cookbook](/cookbook/relative-links.md). -->
+
+**Reason**: This is to make trailing slash behavior consistent: by default all routes allow a trailing slash. It can be disabled by using the `strict` option and manually appending (or not) a slash to the routes.
+
+<!-- TODO: maybe a cookbook entry -->
+
+### `$route` properties Encoding
+
+Decoded values in `params`, `query`, and `hash` are now consistent no matter where the navigation is initiated (older browsers will still produce unencoded `path` and `fullPath`). The initial navigation should yield the same results as in-app navigations.
+
+Given any [normalized route location](/api/#routelocationnormalized):
+
+- Values in `path`, `fullPath` are not decoded anymore. They will appear as provided by the browser (most browsers provide them encoded). e.g. directly writing on the address bar `https://example.com/hello world` will yield the encoded version: `https://example.com/hello%20world` and both `path` and `fullPath` will be `/hello%20world`.
+- `hash` is now decoded, that way it can be copied over: `router.push({ hash: $route.hash })` and be used directly in [scrollBehavior](/api/#scrollbehavior)'s `el` option.
+- When using `push`, `resolve`, and `replace` and providing a `string` location or a `path` property in an object, **it must be encoded** (like in the previous version). On the other hand, `params`, `query` and `hash` must be provided in its unencoded version.
+- The slash character (`/`) is now properly decoded inside `params` while still producing an encoded version on the URL: `%2F`.
+- The `+` character (`%2B` in its encoded form) no longer receives special treatment when found on the query section of the URL. It used to be encoded to deal with [legacy systems using `application/x-www-form-urlencoded`](https://url.spec.whatwg.org/#urlencoded-parsing). This can still be customized when providing custom [parsing and stringifying for `query`](/api/#stringifyquery) because they are responsible of encoding and decoding query params.
+
+**Reason**: This allows to easily copy existing properties of a location when calling `router.push()` and `router.resolve()`, and make the resulting route location consistent across browsers. `router.push()` is now idempotent, meaning that calling `router.push(route.fullPath)`, `router.push({ hash: route.hash })`, `router.push({ query: route.query })`, and `router.push({ params: route.params })` will not create extra encoding.
+
+### TypeScript changes
 
 To make typings more consistent and expressive, some types have been renamed:
 
@@ -375,3 +383,11 @@ To make typings more consistent and expressive, some types have been renamed:
 | RouteConfig    | RouteRecordRaw          |
 | Location       | RouteLocation           |
 | Route          | RouteLocationNormalized |
+
+## New Features
+
+Some of new features to keep an eye on in Vue Router 4 include:
+
+- [Dynamic Routing](/api/#addroute-2)
+- [Composition API](/guide/advanced/composition-api.md)
+<!-- - Custom History implementation -->