## Vue 3 migration notes
---
### Stores file structure
All stores are now placed in /stores instead of in each separate app.
For example
`/src/apps/Search/store.ts` is now `/src/stores/search/index.ts`
---
### Vue-file Converson Flow:
* Install `eslint-plugin-vuetify`!! it will give hints on deprecated vuetify attributes
1. Use `vue-declassify Component.Vue` to convert the file
* if it fails, try:
1. Cut any vuex Store/State decourators at the top of the component. Such as:
`@RoutesStore.Action getRoutes: any`
`@OnlineOrderStore.Action fetchCustomerInfo: any`
2. if there is a `created()` function, try cutting it and then putting it in manually inside <script setup>...</script>
3. Remove wrapping `Vue.Extends(...);` from default export
4. Remove any `@Emit ...` decorators since they can't be automatically converted
5. Remove access modifiers (so far only `private` before functions)
6. Remove return-types from functions (data, computed, watch)
7. Use https://tjk.github.io/vue-o2c/
8. Fix remaining bugs.. :cry:
### vue-facing-decorator
Lingering 'vue-facing-decorator' can safely be removed:
~~```import Component from 'vue-facing-decorator'```~~
---
### v-slot:activator and v-on
Before:
<v-tooltip right>
<template v-slot:activator="{ on, attrs }">
<v-btn v-on="on" :attrs="attrs" ...
After:
<v-tooltip right>
<template v-slot:activator="{ props }">
<v-btn v-bind="props" ...
---
### Dependency changes
* Before we used `vue-notification`, which only supports Vue 2.x
For now I use `@kyvg/vue3-notification` instead which is *almost* a drop-in replacement.
* Instead of `vue-clipboard2` we now use `@soerenmartius/vue3-clipboard. I have tried multiple alternatives, such as `vue-clipboard3` but typescript support is lacking.
---
### Path-aliases such as '@Search'
Previously defined in `vue.config.ts`, now defined in `vite.config.ts`:
export default defineConfig({
...
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'@Search': fileURLToPath(new URL('./src/apps/Search', import.meta.url)),
},
...
also in tsconfig.app.json
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@Search/*": ["src/apps/Search/*"],
...
---
### Props
* Wrap props with defineProps
* no need to create a variable unless it's used in <script>...</script>, (any use in the <template /> is fine anyway and inferred from defineProps)
* If a variable is needed we call it just 'props' for consistency
* Vue.extend() is no longer used
* object is flattened and `props: { ...` can be removed:
Before:
const SecondaryButtonProps = Vue.extend({
props: {
disabled: Boolean,
small: Boolean,
icon: Boolean,
...
},
})
After:
defineProps({
disabled: Boolean,
small: Boolean,
icon: Boolean,
...
})
---
### Emits
* `@Emit` decorators are not converted automatically.
* Best guess is to defineEmits and then later use that emit.
* I'm guessing the return isn't needed anymore, (but it doesn't hurt either)
Before:
@Emit()
click(e: any) {
return e
}
After:
const emit = defineEmits(['click'])
function click(e: any) {
emit('click', e)
}
---
### Watch and props
* `$this` is no longer used. Instead use a props-variable for defineProps
* callbacks are no longer looked up by name, just reference directly
Before:
watch(() => $this.value, 'onValueChanged')
After:
const props = defineProps({value: { ... }});
watch(() => props.value, onValueChanged)
---
### Vuetify themes:
After conversion you might end up with:
const $vuetify = inject('vuetify')
...
return $vuetify.theme.dark
Instead we use available hooks (theme.current seems to be correct?):
import { useTheme } from 'vuetify';
const theme = useTheme();
...
return theme.current.value.dark