中国蓝tv手机版
143.87MB · 2025-10-13
v-model
不仅限于原生表单元素,它同样可以优雅地应用于自定义组件。
但你是否遇到过这些问题?
本文将手把手教你如何在自定义组件中实现 v-model
,并深入其工作原理。
v-model
是一个 语法糖,它简化了父子组件之间的双向数据绑定。
<custom-input v-model="message" />
等价于:
<custom-input
:value="message"
@input="message = $event"
/>
<!-- CustomInput.vue -->
<template>
<div class="custom-input">
<input
:value="value"
@input="$emit('input', $event.target.value)"
:placeholder="placeholder"
/>
</div>
</template>
<script>
export default {
name: 'CustomInput',
props: ['value'], // 接收父组件传来的 value
emits: ['input'], // 明确声明触发的事件(Vue 3 推荐)
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请输入内容'
}
}
};
</script>
<!-- ParentComponent.vue -->
<template>
<div>
<h3>消息:{{ message }}</h3>
<custom-input v-model="message" placeholder="请输入消息" />
</div>
</template>
<script>
import CustomInput from './CustomInput.vue';
export default {
components: { CustomInput },
data() {
return {
message: 'Hello'
};
}
};
</script>
message
→ value
prop;input
事件 → $emit('input', 新值)
→ 父组件更新 message
。如果组件本身需要 value
prop 用于其他用途(如复选框),怎么办?
model
选项(Vue 2)<!-- ToggleSwitch.vue -->
<template>
<label class="switch">
<input
type="checkbox"
:checked="isChecked"
@change="$emit('change', $event.target.checked)"
/>
<span class="slider"></span>
</label>
</template>
<script>
export default {
name: 'ToggleSwitch',
model: {
prop: 'isChecked', // 自定义 prop 名
event: 'change' // 自定义 event 名
},
props: {
isChecked: {
type: Boolean,
default: false
}
}
};
</script>
<!-- 使用 -->
<toggle-switch v-model="isOn" />
<!-- 等价于 -->
<toggle-switch
:is-checked="isOn"
@change="isOn = $event"
/>
Vue 3 对 v-model
进行了重大升级:
value
prop;v-model
绑定;modelValue
,事件名为 update:modelValue
。<!-- CustomInput.vue (Vue 3) -->
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
v-bind="$attrs"
/>
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
};
</script>
<!-- 父组件 -->
<custom-input v-model="message" />
<!-- 等价于 -->
<custom-input
:model-value="message"
@update:model-value="message = $event"
/>
defineModel
(实验性,Vue 3.4+)<script setup>
const model = defineModel();
// model.value 即绑定的值
</script>
<template>
<input
:value="model.value"
@input="model.value = $event.target.value"
/>
</template>
<!-- CustomSelect.vue -->
<template>
<select :value="modelValue" @change="handleChange">
<option value="">请选择</option>
<option
v-for="option in options"
:key="option.value"
:value="option.value"
>
{{ option.label }}
</option>
</select>
</template>
<script>
export default {
props: {
modelValue: [String, Number],
options: {
type: Array,
required: true
}
},
emits: ['update:modelValue'],
methods: {
handleChange(e) {
this.$emit('update:modelValue', e.target.value);
}
}
};
</script>
<!-- 使用 -->
<custom-select
v-model="selectedCity"
:options="cityOptions"
/>
emits
:在 Vue 3 中,建议显式声明 emits
;.trim
、.number
,可在组件内处理。value
prop;$emit
的事件名写错(如 input
写成 oninput
);value
而非 modelValue
。要点 | 说明 |
---|---|
本质 | :prop + @event 的语法糖 |
Vue 2 | 默认 value prop + input event |
Vue 3 | 默认 modelValue prop + update:modelValue event |
自定义 | 使用 model 选项或 defineModel |
掌握 v-model
在组件中的使用,你就能:
创建可复用的表单组件;
实现复杂的双向数据流;
提升开发效率与代码可读性。