Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.1 KiB
4.1 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>