diff options
Diffstat (limited to 'doc/development/fe_guide/vue3_migration.md')
-rw-r--r-- | doc/development/fe_guide/vue3_migration.md | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/doc/development/fe_guide/vue3_migration.md b/doc/development/fe_guide/vue3_migration.md new file mode 100644 index 00000000000..7ab48db7f76 --- /dev/null +++ b/doc/development/fe_guide/vue3_migration.md @@ -0,0 +1,124 @@ +# Migration to Vue 3 + +In order to prepare for the eventual migration to Vue 3.x, we should be wary about adding the following features to the codebase: + +## Vue filters + +**Why?** + +Filters [are removed](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0015-remove-filters.md) from the Vue 3 API completely. + +**What to use instead** + +Component's computed properties / methods or external helpers. + +## Event hub + +**Why?** + +`$on`, `$once`, and `$off` methods [are removed](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md) from the Vue instance, so in Vue 3 it can't be used to create an event hub. + +**What to use instead** + +Vue docs recommend using [mitt](https://github.com/developit/mitt) library. It's relatively small (200 bytes gzipped) and has a simple API: + +```javascript +import mitt from 'mitt' + +const emitter = mitt() + +// listen to an event +emitter.on('foo', e => console.log('foo', e) ) + +// listen to all events +emitter.on('*', (type, e) => console.log(type, e) ) + +// fire an event +emitter.emit('foo', { a: 'b' }) + +// working with handler references: +function onFoo() {} + +emitter.on('foo', onFoo) // listen +emitter.off('foo', onFoo) // unlisten +``` + +**Event hub factory** + +To make it easier for you to migrate existing event hubs to the new recommended approach, or simply +to create new ones, we have created a factory that you can use to instantiate a new mitt-based +event hub. + +```javascript +import createEventHub from '~/helpers/event_hub_factory'; + +export default createEventHub(); +``` + +Event hubs created with the factory expose the same methods as Vue 2 event hubs (`$on`, `$once`, `$off` and +`$emit`), making them backward compatible with our previous approach. + +## \<template functional> + +**Why?** + +In Vue 3, `{ functional: true }` option [is removed](https://github.com/vuejs/rfcs/blob/functional-async-api-change/active-rfcs/0007-functional-async-api-change.md) and `<template functional>` is no longer supported. + +**What to use instead** + +Functional components must be written as plain functions: + +```javascript +import { h } from 'vue' + +const FunctionalComp = (props, slots) => { + return h('div', `Hello! ${props.name}`) +} +``` + +## Old slots syntax with `slot` attribute + +**Why?** + +In Vue 2.6 `slot` attribute was already deprecated in favor of `v-slot` directive but its usage is still allowed and sometimes we prefer using them because it simplifies unit tests (with old syntax, slots are rendered on `shallowMount`). However, in Vue 3 we can't use old syntax anymore. + +**What to use instead** + +The syntax with `v-slot` directive. To fix rendering slots in `shallowMount`, we need to stub a child component with slots explicitly. + +```html +<!-- MyAwesomeComponent.vue --> +<script> +import SomeChildComponent from './some_child_component.vue' + +export default { + components: { + SomeChildComponent + } +} + +</script> + +<template> + <div> + <h1>Hello GitLab!</h1> + <some-child-component> + <template #header> + Header content + </template> + </some-child-component> + </div> +</template> +``` + +```javascript +// MyAwesomeComponent.spec.js + +import SomeChildComponent from '~/some_child_component.vue' + +shallowMount(MyAwesomeComponent, { + stubs: { + SomeChildComponent + } +}) +``` |