Skip to content

Commit cc0673f

Browse files
Add v-model changes to migration guide (#143)
* feat: added a v-model changes overview * feat: added separation for priority * fix: reverted categorization and fixed v-model * Update src/guide/migration/v-model.md Co-authored-by: Ben Hong <[email protected]> * Update src/guide/migration/v-model.md Co-authored-by: Ben Hong <[email protected]> * Update src/guide/migration/v-model.md Co-authored-by: Ben Hong <[email protected]> Co-authored-by: Ben Hong <[email protected]>
1 parent ca9b26e commit cc0673f

File tree

3 files changed

+148
-55
lines changed

3 files changed

+148
-55
lines changed

src/.vuepress/config.js

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ const sidebar = {
9090
'migration',
9191
'migration/global-api',
9292
'migration/treeshaking',
93+
'migration/v-model',
9394
'migration/functional-components',
9495
'migration/async-components',
9596
'migration/custom-directives'

src/guide/migration.md

-55
Original file line numberDiff line numberDiff line change
@@ -37,58 +37,3 @@ It depends on a few factors:
3737
> If I upgrade to Vue 3, will I also have to upgrade Vuex and Vue Router?
3838
3939
[//]: # 'TODO: still need to see where this lands'
40-
41-
## Built-in Directives
42-
43-
### `v-model` API Change
44-
45-
In Vue 2, the `v-model` directive required developers to always use the `value` prop. And if developers required different props for different purposes, they would have to resort to using `v-bind.sync`. In addition, this hard-coded relationship between `v-model` and `value` led to issues with how native elements and custom elements were handled.
46-
47-
However, with Vue 3, the API for two-way data binding is being standardized in order to reduce confusion and to allow developers more flexibility with the `v-model` directive.
48-
49-
Using v-model in Vue 3
50-
In Vue 3, by detaching the `v-model` from the `value` prop, developers now have the ability to pass arguments to `v-model` which will allow them to create multiple `v-model` bindings on a single component.
51-
52-
```html
53-
<SignupForm v-model:name="”userName”" v-model:email="”userEmail”" />
54-
```
55-
56-
#### Modifiers
57-
58-
In Vue 2.x, hard-coded modifiers such as `.trim` on `v-model` were introduced to provide an intuitive way to solve common scenarios. However,
59-
60-
[//]: # 'TODO: still need to finish, and perhaps add in caveats'
61-
62-
### `v-model.sync` Replaced with `v-model` Argument
63-
64-
In Vue 2, the `.sync` modifier was created in order to offer a shorthand way to create two-way data binding for a prop. For example, in the event we want a child component to update its own title property, we would have done something like this:
65-
66-
**ChildComponent.vue**
67-
68-
```html
69-
this.$emit('onUpdate:title', newTitle)
70-
```
71-
72-
**ParentComponent.vue**
73-
74-
```html
75-
<child-component v-bind:title.sync="pageTitle"></child-component>
76-
```
77-
78-
However, this led to some confusion since two-way data flow is closely tied to the `v-model` directive, whereas `v-bind` is normally used for one-way data flow for props.
79-
80-
#### How to Sync Props in Vue 3
81-
82-
In Vue 3, we no longer need the `.sync` modifier anymore. Similar to how we can listen for changes to a form input value, Vue 3 allows us to perform "two way data binding" on props by allowing you to pass the prop as an argument to `v-model`.
83-
84-
![v-bind anatomy](/images/v-bind-instead-of-sync.png)
85-
86-
Using the example from before, it can now be simplified to:
87-
88-
**ParentComponent.vue**
89-
90-
```html
91-
<child-component v-model:title="pageTitle"></child-component>
92-
```
93-
94-
By passing our prop title to the `v-model` directive, Vue will listen for an `onUpdate:title` event that will be emitted from the child component in order to update the data accordingly.

src/guide/migration/v-model.md

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Changes to `v-model` on custom components
2+
3+
## Overview
4+
5+
In terms of what has changed, at a high level:
6+
7+
- When used on custom components, `v-model` prop and event default names are changed:
8+
- prop: `value` -> `modelValue`;
9+
- event: `input` -> `update:modelValue`;
10+
- Multiple `v-model` bindings on the same component are possible now;
11+
- **BREAKING:** `v-bind`'s `.sync` modifier and component `model` option are removed and replaced with an argument on `v-model`;
12+
- **NEW:** Added the ability to create custom `v-model` modifiers.
13+
14+
For more information, read on!
15+
16+
## Introduction
17+
18+
In Vue 2, the `v-model` directive required developers to always use the `value` prop. And if developers required different props for different purposes, they would have to resort to using `v-bind.sync`. In addition, this hard-coded relationship between `v-model` and `value` led to issues with how native elements and custom elements were handled.
19+
20+
In 2.2 we introduced the `model` component option that allows the component to customize the prop and event to use for `v-model`. However, this still only allowed a single `v-model` to be used on the component.
21+
22+
With Vue 3, the API for two-way data binding is being standardized in order to reduce confusion and to allow developers more flexibility with the `v-model` directive.
23+
24+
## Previous Syntax
25+
26+
In v2, using a `v-model` on a component was an equivalent of passing a `value` prop and emitting an `input` event:
27+
28+
```html
29+
<ChildComponent v-model="pageTitle" />
30+
31+
<!-- would be shorthand for: -->
32+
33+
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
34+
```
35+
36+
If we wanted to change prop or event names to something different, we would need to add a `model` option to `ChildComponent` component:
37+
38+
```html
39+
<!-- ParentComponent.vue -->
40+
41+
<ChildComponent v-model="pageTitle" />
42+
```
43+
44+
```js
45+
// ChildComponent.vue
46+
47+
export default {
48+
model: {
49+
prop: 'title',
50+
event: 'change'
51+
},
52+
props: {
53+
// this allows using the `value` prop for a different purpose
54+
value: String,
55+
// use `title` as the prop which take the place of `value`
56+
title: {
57+
type: String,
58+
default: 'Default title'
59+
}
60+
}
61+
}
62+
```
63+
64+
So, `v-model` in this case would be a shorthand to
65+
66+
```html
67+
<ChildComponent :title="pageTitle" @change="pageTitle = $event" />
68+
```
69+
70+
### Using `v-bind.sync`
71+
72+
In some cases, we might need "two-way binding" for a prop (sometimes in addition to existing `v-model` for the different prop). To do so, we recommended emitting events in the pattern of `update:myPropName`. For example, for `ChildComponent` from the previous example with the `title` prop, we could communicate the intent of assigning a new value with:
73+
74+
```js
75+
this.$emit('update:title', newValue)
76+
```
77+
78+
Then the parent could listen to that event and update a local data property, if it wants to. For example:
79+
80+
```html
81+
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
82+
```
83+
84+
For convenience, we had a shorthand for this pattern with the .sync modifier:
85+
86+
```html
87+
<ChildComponent :title.sync="pageTitle" />
88+
```
89+
90+
## Current Syntax
91+
92+
In v3 `v-model` on the custom component is an equivalent of passing a `modelValue` prop and emitting an `update:modelValue` event:
93+
94+
```html
95+
<ChildComponent v-model="pageTitle" />
96+
97+
<!-- would be shorthand for: -->
98+
99+
<MyBook :modelValue="pageTitle" @update:modelValue="pageTitle = $event" />
100+
```
101+
102+
### `v-model` arguments
103+
104+
To change a model name, instead of a `model` component option, now we can pass an _argument_ to `v-model`:
105+
106+
```html
107+
<ChildComponent v-model:title="pageTitle" />
108+
109+
<!-- would be shorthand for: -->
110+
111+
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
112+
```
113+
114+
![v-bind anatomy](/images/v-bind-instead-of-sync.png)
115+
116+
This also serves as a replacement to `.sync` modifier and allows us to have multiple `v-model`s on the custom component.
117+
118+
```html
119+
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
120+
121+
<!-- would be shorthand for: -->
122+
123+
<ChildComponent
124+
:title="pageTitle"
125+
@update:title="pageTitle = $event"
126+
:content="pageContent"
127+
@update:content="pageContent = $event"
128+
/>
129+
```
130+
131+
### `v-model` modifiers
132+
133+
In addition to v2 hard-coded `v-model` modifiers like `.trim`, now v3 supports custom modifiers:
134+
135+
```html
136+
<ChildComponent v-model.capitalize="pageTitle" />
137+
```
138+
139+
Read more about custom `v-model` modifiers in the [Custom Events](../component-custom-events.html#handling-v-model-modifiers) section.
140+
141+
## Next Steps
142+
143+
For more information on the new `v-model` syntax, see:
144+
145+
- [Using `v-model` on Components](../component-basics.html#using-v-model-on-components)
146+
- [`v-model` arguments](../component-custom-events.html#v-model-arguments)
147+
- [Handling `v-model` modifiers](../component-custom-events.html#v-model-arguments)

0 commit comments

Comments
 (0)