Using numbers, i.e. keyCodes, as v-on modifiers (and defining custom aliases via config.keyCodes) is no longer supported.
Vue 2
Vue.config.keyCodes = {
f1: 112
}
<!-- keyCode -->
<input v-on:keyup.13="submit" />
<!-- alias -->
<input v-on:keyup.enter="submit" />
<!-- keyCode -->
<input v-on:keyup.112="showHelpText" />
<!-- custom alias -->
<input v-on:keyup.f1="showHelpText" />
Vue 3
<input v-on:keyup.enter="submit" /> <input v-on:keyup.f1="showHelpText" />
$on, $off and $once instance methods are removed. Component instances no longer implement the event emitter interface.
Vue 2
// eventBus.js
const eventBus = new Vue()
export default eventBus
// ChildComponent.vue
import eventBus from './eventBus'
export default {
mounted() {
eventBus.$on('custom-event', () => {
console.log('Custom event triggered!')
})
},
beforeDestroy() {
eventBus.$off('custom-event')
}
}
// ParentComponent.vue
import eventBus from './eventBus'
export default {
methods: {
callGlobalCustomEvenet() {
eventBus.$emit('custom-event')
}
}
}
Vue 3
// There is no direct migration path. // Depending on the circumstances, there are various options: // - Props and events should be first choice for parent-child communication. // Siblings can communicate via their parent. // - Provide / inject allow a component to communicate with its slot contents. // This is useful for tightly-coupled components that are always used together. // It can also be used for long-distance communication between components. // where props need to be passed down through many levels of components that // don't need those props themselves. // - Prop drilling can also be avoided by refactoring to use slots. If an interim // component doesn't need the props then it might indicate a problem with // separation of concerns. Introducing a slot in that component allows the // parent to create the content directly, so that props can be passed without // the interim component needing to get involved. // - Global state management, such as Pinia.
filters are removed and no longer supported.
Vue 2
<!-- template -->
<div>{{ accountBalance | currentUSD }}</div>
// script
export default {
props: {
accountBalance: {
type: Number,
required: true
}
},
filters: {
currencyUSD(value) {
return '$' + value
}
}
}
Vue 3
<!-- template -->
<div>{{ accountInUSD }}</div>
// script
export default {
props: {
accountBalance: {
type: Number,
required: true
}
},
computed: {
accountInUSD() {
return '$' + this.accountBalance
}
}
}
Support for the inline-template feature has been removed.
Vue 2
<ChildComponent inline-template :msg="parentMsg">
{{ msg }} {{ childState }}
</ChildComponent>
Vue 3
<!-- ParentComponent.vue -->
<ChildComponent v-slot="{ childState }">
{{ parentMsg }} {{ childState }}
</ChildComponent>
<!-- ChildComponent.vue -->
<template>
<slot :childState="childState" />
</template>
The $children instance property has been removed and is no longer supported.
Vue 2
<!-- template -->
<div>
<my-button>Change logo</my-button>
</div>
// script
import MyButton from './MyButton'
export default {
components: {
MyButton
},
mounted() {
console.log(this.$children)
}
}
Vue 3
<!-- template -->
<div>
<my-button ref="buttonRef">Change logo</my-button>
</div>
// script
import { ref, onMounted } from 'vue'
import MyButton from './MyButton'
export default {
components: {
MyButton
},
setup() {
const buttonRef = ref(null)
onMounted(() => {
console.log(buttonRef.value)
})
return {
buttonRef
}
}
}
The propsData option, used to pass props to the Vue instance during its creation, is removed.
Vue 2
const Comp = Vue.extend({
props: ['username'],
template: '<div>{{ username }}</div>'
})
new Comp({
propsData: {
username: 'Evan
}
})
Vue 3
const app = createApp(
{
props: ['username'],
template: '<div>{{ username }}</div>
},
{ username: 'Evan' }
)