foreword
v-model can be used on components for two-way binding.
First let's recall the usage of v-model on native elements:
<input v-model="firstName" />
Behind the scenes, the template compiler does a more verbose equivalent expansion of the v-model . So the code above is actually equivalent to the following:
<input
:value="firstName"
@input="firstName = $event.target.value"
/>
default usage
parent component
<template>
<div>
<h1>{
{ first }}-{
{ last }}</h1>
<UserName
:firstName="first"
:lastName="last"
@update:firstName="func1"
@update:lastName="func2"
/>
</div>
</template>
<script>
import UserName from "./UserName.vue";
export default {
name: "V-Model",
components: {
UserName,
},
data() {
return {
first: "000",
last: "123",
};
},
methods: {
// 默认用法
func1(val) {
this.first = val;
},
func2(val) {
this.last = val;
},
},
};
</script>
Subassembly
<template>
<div>
<input v-model="first" type="text" @input="input1" />
<input v-model="last" type="text" @input="input2" />
</div>
</template>
<script>
export default {
name: "UserName",
props: ["firstName", "lastName"],
data() {
return {
first: this.firstName,
last: this.lastName,
};
},
methods: {
input1() {
this.$emit("update:firstName", this.first);
},
input2() {
this.$emit("update:lastName", this.last);
},
},
};
</script>
The above can realize the two-way binding of parent-child components
.sync wording
Adding .sync when passing parameters will simplify the above writing, and the parent component does not need to define an update trigger function (update)
<UserName :firstName.sync="first" />
would be expanded to:
<UserName :firstName="first" @update:firstName="val => first = val"></UserName>
When the child component needs to update the value of firstName , it needs to explicitly trigger an update event:
this.$emit('update:firstName', newValue)
parent component
<template>
<div>
<h1>{
{ first }}-{
{ last }}</h1>
<UserName :firstName.sync="first" :lastName.sync="last" />
</div>
</template>
<script>
import UserName from "./UserName.vue";
export default {
name: "V-Model",
components: {
UserName,
},
data() {
return {
first: "000",
last: "123",
};
},
methods: {
},
};
</script>
Subassembly
<template>
<div>
<input type="text" :value="firstName" @input="$emit('update:firstName', $event.target.value)" />
<input type="text" :value="lastName" @input="$emit('update:lastName', $event.target.value)" />
</div>
</template>
<script>
export default {
name: "UserName",
components: {},
props: ["firstName", "lastName"],
data() {
return {};
},
methods: {},
};
</script>
The above can also achieve two-way binding of parent-child components
Bind a single v-model
When used on a component, v-model will be expanded as follows:
<UserName v-model="first" />
<!-- 上面等同于下面的写法 -->
<UserName
:modelValue="first"
@input="first= $event.target.value"
/>
parent component
<template>
<div>
<h1>{
{ first }}-{
{ last }}</h1>
<UserName v-model="first" />
</div>
</template>
<script>
import UserName from "./UserName.vue";
export default {
name: "V-Model",
components: {
UserName,
},
data() {
return {
first: "000",
last: "123",
};
},
methods: {
},
};
</script>
Subassembly
<template>
<div>
<input
type="text"
:value="firstName"
@input="$emit('update', $event.target.value)"
/>
</div>
</template>
<script>
export default {
name: "UserName",
components: {},
props: ["firstName"],
model: {
prop: "firstName",
event: "update",
},
data() {
return {};
},
};
</script>
Single input box binding is now possible
If there is an error in the article, please ask everyone to ask questions, I would be very grateful. If you don't understand, you can comment, and I will reply one by one.
If the article is helpful to everyone, I hope you can give it a thumbs up and encourage it. There will be a long way to go to work together in the future, and the road will be long and difficult.