Vue 3 breaking changes checklist
Every change below can break or silently change a Vue 2 app when it runs on Vue 3. vueleap checks all of them automatically and links each one to the official migration guide.
Instead of reading the list, run npx vueleap in your project to see which of these apply, with file and line numbers.
41 checks
Templates
| Rule | Severity | What changes | @vue/compat flag | Auto fix | Docs |
|---|---|---|---|---|---|
filters | error | Filters are removed Filters ( {{ price | currency }}, Vue.filter, the filters option) no longer exist. Replace them with method calls, computed properties or global properties. | COMPILER_FILTERS FILTERS | No | Guide |
hook-events | warning | hook: lifecycle events are renamed Listening to a child lifecycle with @hook:mounted becomes @vue:mounted. $on('hook:...') no longer works. | INSTANCE_EVENT_HOOKS | Yes | Guide |
sync-modifier | error | .sync is replaced by v-model:prop:title.sync="value" becomes v-model:title="value". The child keeps emitting update:title. | COMPILER_V_BIND_SYNC | Yes | Guide |
native-modifier | warning | The .native modifier is removed Listeners not declared in the child emits option are added to its root element. Remove .native and declare the events the child really emits. | COMPILER_V_ON_NATIVE | No | Guide |
keycode-modifiers | error | KeyCode modifiers are removed Numeric modifiers such as @keyup.13 must use key names such as @keyup.enter. | V_ON_KEYCODE_MODIFIER | Yes | Guide |
functional-components | error | Functional components changed The functional attribute on <template> and the functional: true option are gone. Use a normal component (the performance gap is negligible) or a plain function. | COMPONENT_FUNCTIONAL | No | Guide |
inline-template | error | inline-template is removed Move the inner markup into the component itself, or pass it through a default slot. | COMPILER_INLINE_TEMPLATE | No | Guide |
template-v-for-key | error | Key must be on <template v-for> With <template v-for>, the key belongs on the <template> tag. Keys on its children are a compile error in Vue 3. | none | No | Guide |
v-if-v-for | error | v-if now has higher priority than v-for On the same element, v-if is evaluated first, so it cannot use the v-for variable. Filter the list in a computed property or move v-if to a wrapper. | COMPILER_V_IF_V_FOR_PRECEDENCE | No | Guide |
v-bind-object-order | warning | v-bind="object" is order sensitive Attributes declared before v-bind="obj" can now be overridden by the object. Move v-bind="obj" first if the explicit attributes should win, as they did in Vue 2. | COMPILER_V_BIND_OBJECT_ORDER | No | Guide |
transition-group-root | info | <transition-group> renders no wrapper Without a tag prop, <transition-group> no longer renders a <span>. Add tag="span" if your CSS relies on it. | TRANSITION_GROUP_ROOT | No | Guide |
deprecated-slot-syntax | error | slot and slot-scope attributes are removed The slot, slot-scope and scope attributes were deprecated in Vue 2.6 and removed in Vue 3. Use v-slot (or #name). | none | No | Guide |
is-on-element | warning | is on native elements needs the vue: prefix<tr is="my-row"> now creates a customized built-in element. Use is="vue:my-row" to render a Vue component. | COMPILER_IS_ON_ELEMENT | No | Guide |
Scripts and component options
| Rule | Severity | What changes | @vue/compat flag | Auto fix | Docs |
|---|---|---|---|---|---|
listeners | error | $listeners is removed Event listeners are now part of $attrs. v-on="$listeners" can usually be dropped when v-bind="$attrs" is present. | INSTANCE_LISTENERS | No | Guide |
scoped-slots | error | $scopedSlots is removed All slots are exposed on $slots as functions. $scopedSlots.x becomes $slots.x. | INSTANCE_SCOPED_SLOTS | Yes | Guide |
event-emitter | error | $on, $off and $once are removed Instances are no longer event emitters, so event buses built on new Vue() stop working. Use props and emits, provide/inject, a store, or a small library such as mitt. | INSTANCE_EVENT_EMITTER | No | Guide |
set-delete | error | $set, $delete, Vue.set and Vue.delete are removed Vue 3 reactivity is based on Proxy, so plain assignment and the delete operator are tracked. Replace this.$set(obj, key, value) with obj[key] = value. | GLOBAL_SET GLOBAL_DELETE INSTANCE_SET INSTANCE_DELETE | No | Guide |
children | error | $children is removed Use template refs to reach child component instances. | INSTANCE_CHILDREN | No | Guide |
destroy | error | $destroy is removed Components can no longer destroy themselves. Unmount the app with app.unmount() or remove the component with v-if. | INSTANCE_DESTROY | No | Guide |
global-mount | error | new Vue() is replaced by createApp() Create the root with createApp(App) and mount it with app.mount('#app'). | GLOBAL_MOUNT | No | Guide |
global-api | error | Global Vue API moved to the app instanceVue.component, Vue.use, Vue.mixin and Vue.directive become app.component, app.use, app.mixin and app.directive. Vue.nextTick and Vue.observable become named imports (nextTick, reactive). | GLOBAL_OBSERVABLE GLOBAL_PRIVATE_UTIL | No | Guide |
global-prototype | error | Vue.prototype is replaced by app.config.globalProperties Move Vue.prototype.$http = http to app.config.globalProperties.$http = http, or use provide/inject. | GLOBAL_PROTOTYPE | No | Guide |
global-extend | error | Vue.extend is removed Use defineComponent for type inference, the extends option for inheritance and createApp to mount. | GLOBAL_EXTEND | No | Guide |
config-production-tip | warning | Vue.config.productionTip is removed The option no longer exists. The statement can simply be deleted. | CONFIG_PRODUCTION_TIP | Yes | Guide |
config-ignored-elements | warning | Vue.config.ignoredElements is replaced by isCustomElement Use compilerOptions.isCustomElement in your build config (or app.config.compilerOptions.isCustomElement with the runtime compiler). It takes a function instead of strings or regular expressions. | CONFIG_IGNORED_ELEMENTS | No | Guide |
config-key-codes | error | Vue.config.keyCodes is removed Custom key code aliases are gone. Use kebab-case key names such as @keyup.page-down. | CONFIG_KEY_CODES | No | Guide |
global-config | warning | Vue.config moved to app.config Global configuration now lives on app.config. Some options (silent, devtools) were removed. | CONFIG_SILENT CONFIG_DEVTOOLS CONFIG_OPTION_MERGE_STRATS | No | Guide |
destroy-hooks | error | beforeDestroy and destroyed are renamedbeforeDestroy is now beforeUnmount and destroyed is now unmounted. The old hooks are silently ignored. | OPTIONS_BEFORE_DESTROY OPTIONS_DESTROYED | Yes | Guide |
directive-hooks | error | Custom directive hooks are renamed Directive hooks follow the component lifecycle: bind is beforeMount, inserted is mounted, componentUpdated is updated, unbind is unmounted, and update was removed. | CUSTOM_DIR | Yes | Guide |
component-v-model | error | v-model on components uses modelValue A component used with v-model now receives modelValue and must emit update:modelValue. The value prop, the input event and the model option no longer apply. | COMPONENT_V_MODEL | No | Guide |
render-function-h | error | Render functions no longer receive h Import h from vue instead of taking it as an argument. The VNode props shape is also flatter (on, attrs and domProps are gone). | RENDER_FUNCTION | No | Guide |
attrs-class-style | info | $attrs now includes class and style Check components that forward $attrs, especially with inheritAttrs: false, because class and style now travel with them. | INSTANCE_ATTRS_CLASS_STYLE | No | Guide |
data-object | error | data must be a function Declaring data as a plain object is no longer allowed, including on the root instance. Use data() { return { ... } }. | OPTIONS_DATA_FN | No | Guide |
watch-array | info | Array watchers need deep for mutations Watching an array only fires when the array is replaced. Add deep: true if you rely on push, splice and friends. | WATCH_ARRAY | No | Guide |
composition-api-plugin | warning | @vue/composition-api is built in Import the Composition API from vue and remove the plugin. Some helpers (set, del) have no Vue 3 equivalent. | none | No | Guide |
Styles
| Rule | Severity | What changes | @vue/compat flag | Auto fix | Docs |
|---|---|---|---|---|---|
transition-classes | warning | Transition classes renamed.v-enter is now .v-enter-from and .v-leave is now .v-leave-from. The enter-class and leave-class props are now enter-from-class and leave-from-class. | TRANSITION_CLASSES | Yes | Guide |
Dependencies
| Rule | Severity | What changes | @vue/compat flag | Auto fix | Docs |
|---|---|---|---|---|---|
vue-version | warning | Vue 2 dependency Upgrade vue to version 3. During the migration, alias vue to @vue/compat to run Vue 2 code on Vue 3. | none | No | Guide |
vue2-tooling | warning | Vue 2 build or test tooling Compilers, loaders and test utilities are versioned with Vue. Each one has a Vue 3 replacement. | none | No | Guide |
vue-router-v3 | error | vue-router 3 does not support Vue 3 Upgrade to vue-router 4: new VueRouter() becomes createRouter(), mode becomes history: createWebHistory(), and catch-all routes need a custom regex. | none | No | Guide |
vuex-v3 | error | Vuex 3 does not support Vue 3 Upgrade to Vuex 4 ( createStore), or move to Pinia, the official recommendation for new Vue 3 code. | none | No | Guide |
vue2-libraries | error | Vue 2 only library This library only supports Vue 2. Each finding names its Vue 3 successor. | none | No | Guide |
No check matches this search.
How vueleap detects them
Templates are parsed with @vue/compiler-dom (the Vue 3 compiler parser, which still understands Vue 2 syntax), scripts with @babel/parser (JavaScript, TypeScript, JSX and decorators), styles with a comment aware scanner, and dependencies from package.json. Component options are only checked on objects that really look like components, so a { destroyed: true } flag is not mistaken for a lifecycle hook.
More guides
How to migrate Vue 2 to Vue 3A step by step plan using the migration build and vueleap.Read the guide@vue/compat build flags explainedHow configureCompat works and which flags you need.Read the guideVue filters removed in Vue 3Replace filters with methods, computed properties or globals.Read the guideEvent bus in Vue 3Replace $on, $off and $once with mitt, props or a store.Read the guidev-model changes in Vue 3modelValue, update:modelValue, v-model arguments and .sync.Read the guideVue 2 end of lifeWhat the end of support means and how to plan the upgrade.Read the guide