963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
4.3 KiB
4.3 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| v-model Breaking Changes from Vue 2 to Vue 3 | HIGH | Vue 3 changed v-model prop/event names and removed .sync modifier - migration required | migration |
|
v-model Breaking Changes from Vue 2 to Vue 3
Impact: HIGH - Vue 3 fundamentally changed how v-model works on custom components. Code using the Vue 2 pattern will silently fail - the component won't receive the prop value and changes won't propagate to the parent.
Task Checklist
- Change prop name from
valuetomodelValue - Change event name from
inputtoupdate:modelValue - Replace
.syncmodifier withv-model:propName - Remove
modelcomponent option (use defineModel or named v-model) - Update any v-bind.sync to v-model with named argument
Key Breaking Changes
| Feature | Vue 2 | Vue 3 |
|---|---|---|
| Default prop | value |
modelValue |
| Default event | input |
update:modelValue |
| Custom name | model: { prop, event } |
v-model:customName |
| Sync modifier | v-bind:prop.sync |
v-model:prop |
| Multiple models | Not supported | Fully supported |
Vue 2 Pattern (No longer works in Vue 3):
<!-- Vue 2 Child Component -->
<script>
export default {
props: ['value'], // WRONG in Vue 3
methods: {
update(val) {
this.$emit('input', val); // WRONG in Vue 3
},
},
};
</script>
<template>
<input :value="value" @input="update($event.target.value)" />
</template>
Vue 3 Pattern (Options API):
<!-- Vue 3 Child Component -->
<script>
export default {
props: ['modelValue'], // Changed from 'value'
emits: ['update:modelValue'], // Declare emits
methods: {
update(val) {
this.$emit('update:modelValue', val); // Changed from 'input'
},
},
};
</script>
<template>
<input :value="modelValue" @input="update($event.target.value)" />
</template>
Vue 3 Pattern (Composition API with defineModel):
<!-- Vue 3 Child Component - Recommended -->
<script setup>
const model = defineModel(); // Handles prop and emit automatically
</script>
<template>
<input v-model="model" />
</template>
Migrating the .sync Modifier
Vue 2's .sync modifier is removed. Use named v-model instead.
Vue 2:
<!-- Parent -->
<MyComponent :title.sync="pageTitle" />
<!-- Child -->
<script>
export default {
props: ['title'],
methods: {
updateTitle(val) {
this.$emit('update:title', val); // .sync pattern
},
},
};
</script>
Vue 3:
<!-- Parent -->
<MyComponent v-model:title="pageTitle" />
<!-- Child with defineModel -->
<script setup>
const title = defineModel('title');
</script>
<template>
<input v-model="title" />
</template>
<!-- Child with manual props/emits -->
<script setup>
const props = defineProps(['title']);
const emit = defineEmits(['update:title']);
</script>
<template>
<input :value="props.title" @input="emit('update:title', $event.target.value)" />
</template>
Migrating Custom model Option
Vue 2's model component option is removed.
Vue 2:
<script>
export default {
model: {
prop: 'checked',
event: 'change',
},
props: ['checked'],
};
</script>
Vue 3:
<!-- Use named v-model argument instead -->
<!-- Parent -->
<MyCheckbox v-model:checked="isChecked" />
<!-- Child -->
<script setup>
const checked = defineModel('checked');
</script>
Multiple v-model Bindings (New in Vue 3)
Vue 3 allows multiple v-model directives on a single component:
<!-- Parent -->
<UserForm v-model:firstName="first" v-model:lastName="last" v-model:email="email" />
<!-- Child -->
<script setup>
const firstName = defineModel('firstName');
const lastName = defineModel('lastName');
const email = defineModel('email');
</script>
<template>
<input v-model="firstName" placeholder="First Name" />
<input v-model="lastName" placeholder="Last Name" />
<input v-model="email" type="email" placeholder="Email" />
</template>