在 vue 的自定义组件中实现 v-model

vue2 自定义组件的 v-model

1
2
3
4
5
6
7
8
9
<input v-model="val">
<!-- 等价于 -->
<input :value="val" @input="val = $event.target.value">

...
return{
val:''
}
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 自定义组件 -->
<template>
<input :value="value" @input="updateSomething">
<template/>
props:{
// vue2 默认会使用 value这个变量名
value:String
},
mathod:{
updateSomething(e){
// vue2 默认使用 input 事件
this.$emit("input",e.target.checked)
}
}
...

vue2 自定义属性名或者事件

1
2
3
4
5
6
7
8
<!-- 通过自定义事件更新 -->
<ChildComponent v-model="checked" />

...
return {
checked:false
}
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<input type="checkbox" :title="checked" @change="updateSomething">
<template/>

// 子组件定义
export default {
// 自定义事件名或属性名要在model中定义
model: {
prop: checked,
event: change
}
props: {
checked: {
checked:Boolean
},
methods:{
// 通过发布自定义事件更新
updateSomething(e){
this.$emit("change",e.target.checked)
}
}
}
}

缺点

  1. 无论是原生组件还是自定义组件都只能存在一个 v-model
  2. 繁琐

vue3 自定义组件的 v-model

Vue3 中则不在使用 model 选项而是通过 props 参数来实现 v-model

1
2
3
4
5
6
<ChildComponent v-model="pageTitle" />
<!-- 相当于 -->
<ChildComponent
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ChildComponent.vue

export default defineComponent({
props: {
modelValue: String // 以前在model属性中是`value:String`
},
setup(props,context){
const changePageTitle = (e: KeyboardEvent) => {
const targetValue = (e.target as HTMLInputElement).value
inputRef.val = targetValue
context.emit('update:modelValue', title) // 以前是 `this.$emit('input', title)`
}
}
})

vue3 的 v-model 中定义多个属性

1
2
3
4
5
6
7
8
9
10
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />

<!-- 是以下的简写: -->

<ChildComponent
:title="pageTitle"
@update:title="pageTitle = $event"
:content="pageContent"
@update:content="pageContent = $event"
/>

v-model | Vue.js (vuejs.org)