Pasos a seguir para migrar un componente de Vue 2 a Vue 3, manteniendo Options API. He seguido los pasos que se indican en estos dos enlaces:
- https://labs.etsi.org/rep/help/development/fe_guide/vue3_migration.md
- https://www.vuemastery.com/blog/migration/
A continuación pongo los que me he encontrando modificando los componentes de src/app/shared (o alguno que sospeche que nos podemos encontrar en otros componentes).
1. export default defineComponent
En vez de:
<script>
export default {
...
};
</script>
Hay que cambiarlo a:
<script>
import { defineComponent } from 'vue';
export default defineComponent({
...
});
</script>
2. Especificar emits
Hay que añadir un campo emits que contenga un array con los nombres de los eventos que emite el componente. Por ejemplo, este componente Switcher emite un evento changeSwitcher en un método, pues hay que especificarlo así:
export default defineComponent({
name: 'Switcher',
emits: ['changeSwitcher'],
...
...
});
3. Cambiar this.$refs de v-for
Cuando utilizamos ref en un v-for , antes se podían acceder a todos los elementos con this.$refs.nombreRef , y te devolvía un array.
Ahora, en Vue 3, habría que asignarle una función que se ejecutará automáticamente. Por ejemplo:
<template>
<ul>
<li v-for="item in items" :key="item.id" :ref="setNode">
...
</li>
</ul>
</template>
// later
...
data() {
return {
myNodes: [] // create an array to hold the nodes
}
},
beforeUpdate() {
this.myNodes = [] // reset empty before each update
},
methods: {
setNode(el) { // this will be called automatically
this.myNodes.push(el) // add the node
}
},
updated() {
console.log(this.myNodes) // finally, a list of HTML node references
},
Aquí, cada vez que se actualiza el DOM, se resetea el array myNodes que se ha definido en el data(), y se ejecuta setNode para asignar cada uno de los elementos del v-for. De esta forma, this.myNodes sustituiría a this.$refs.myNodes.
4. Cambiar la propiedad y evento de v-model
Si para utilizar nuestro componente se utiliza v-model, es decir, que tiene una prop llamada value y emite un evento $emit("input"), tendremos que cambiar estas dos cosas:
- La prop pasará a llamarse modelValue.
- Y el evento (recordad tenerlo en el campo emits del componente) deberá ser $emit("update:modelValue").
5. beforeDestroy y destroyed cambian de nombre
Pasan a llamarse beforeUnmount y unmounted.
6. Cambiar .sync
v-bind.sync o @prop.sync ya no están disponibles, ahora se utiliza v-model, seguido del nombre de la prop: v-model:propName="loQueSea". v-model se ha mejorado en Vue 3, dando esta opción de enlazarlo a la prop que queramos, y se comportará como cuando en Vue 2 incluíamos el modificador .sync.
Si el linter da error por utilizarlo, habrá que añadir la siguiente regla:
"rules": {
"vue/no-v-model-argument": "off" // ADD
}
7. Deep watchers
Para reaccionar a los cambios en objetos y objetos que están dentro de arrays, tenemos que añadir deep = true. Por defecto, los watchers sólo se van a disparar cuando se asigne un nuevo valor, o en el caso de los arrays también cuando se introduzcan o eliminen elementos, pero no cuando se modifica una propiedad de los objetos. Con deep = true sí se podrán capturar estos cambios.
watch: {
someObject: {
handler(newValue, oldValue) {
// Note: `newValue` will be equal to `oldValue` here
// on nested mutations as long as the object itself
// hasn't been replaced.
},
deep: true
}
}
* Actualizar Vuex y Vue Router
Hay que actualizarlos a Vuex 4 y Vue Router, respectivamente.