组件上的 v-model
💥💥💥
环境为:
Vue3
1. 原生元素上的 v-model
<p>{{ msg }}</p>
<input v-model="msg" />
<!-- 上面的代码其实等价于下面这段 (编译器会对 v-model 进行展开): -->
<input :value="msg" @input="msg = $event.target.value" />
2. 组件上的 v-model
2.1 组件v-model的展开
<template>
<p>{{ msg }}</p>
<!-- 组件上的v-model -->
<CustomeInput v-model="msg"></CustomeInput>
</template>
<script>
import CustomeInput from './components/CustomeInput.vue';
export default {
name: 'App',
components: {
CustomeInput
},
data() {
return {
msg: '我是付常涛'
};
}
};
</script>
v-model
展开如下:
<CustomInput
:modelValue="msg"
@update:modelValue="newValue => msg = newValue"
/>
✨✨✨
v-model="msg"
,默认将属性modelValue
当做 props 传进组件,并接收组件内名为update:modelValue
的自定义事件。
2.2 组件内部
通过点击按钮,可以发现App组件和CustomeInput组件
中的msg/modelValue
发生了改变。
<template>
<p>
<strong>{{ modelValue }}</strong>
</p>
<p><button @click="update">更改msg</button></p>
</template>
<script>
export default {
// props 接收
props: ['modelValue'],
// 注册自定义事件
emits: ['update:modelValue'],
methods: {
update() {
this.$emit('update:modelValue', 'fct');
}
}
};
</script>
2.3 在自定义组件内与父组件的 msg 保持同步
在自定义组件中使用
input
,实现组件内输入的内容动态绑定App组件的msg
2.3.1 v-model 手动展开
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
2.3.2 v-model + 计算属性
<template>
<input v-model="modelValueComputed" />
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
computed: {
modelValueComputed: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
}
}
}
}
</script>
3. 组件上多个 v-model
当组件上有一个v-model
时,都是使用 modelValue
作为 prop,并以 update:modelValue
作为对应的事件。
当一个组件上有多个
v-model
时如何区分传入组件的prop?
v-model
其实有参数:
v-model='msg'
其实等于v-model:modelValue='msg'
组件上的多个v-model:
// App.vue
<h2>{{ msg }}</h2>
<h2>{{ title }}</h2>
<MyComponent v-model='msg' v-model:title="title" />
子组件中不仅需要声明modelValue
prop 还得声明title
prop。并通过触发 update:title
事件更新父组件值。
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
<input
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
</template>
<script>
export default {
props: ['title', 'modelValue'],
emits: ['update:title', 'update:modelValue']
}
</script>