在 Vue.js 中,当使用 v-model
指令在自定义组件上时,默认情况下,它期望组件内部有一个名为 value
的 prop 和一个名为 input
的事件,以形成双向绑定。然而,如果你想在自定义组件中监听原生事件(如 input
、change
等),并希望这些事件能影响父组件中通过 v-model
绑定的数据,你需要手动设置 v-model
的 prop 和事件,并在组件内部处理这些原生事件。
1. 自定义组件的 v-model
首先,明确 v-model
在自定义组件中的工作原理。默认情况下,v-model="someData"
会被展开为 :value="someData" @input="someData = $event"
。但在自定义组件中,你可以自定义这些 prop 和事件。
2. 监听原生事件并触发自定义事件
如果你想在自定义组件中监听原生事件(如 input
),并希望这些事件能更新父组件的 v-model
绑定的数据,你可以在组件内部监听这些原生事件,并触发一个自定义事件(通常命名为 input
),该事件将携带更新后的值。
示例
假设你有一个自定义的输入框组件 CustomInput.vue
,你希望它监听原生的 input
事件,并更新父组件中 v-model
绑定的数据。
<!-- CustomInput.vue -->
<template>
<input
:value="value"
@input="$emit('update:value', $event.target.value)"
type="text"
>
</template>
<script>
export default {
props: ['value'],
// 这里没有显式声明 `input` 事件,因为我们使用自定义事件 `update:value`
// Vue 2.2.0+ 支持 `.sync` 修饰符,它等价于监听 `update:value` 事件
}
</script>
然而,为了使这个组件能更无缝地与 v-model
一起工作,你可能想直接使用 input
事件作为自定义事件名,因为 v-model
默认就是监听 input
事件的。
<!-- CustomInput.vue -->
<template>
<input
:value="modelValue"
@input="$emit('input', $event.target.value)"
type="text"
>
</template>
<script>
export default {
// 在 Vue 3 中,推荐使用 `modelValue` 和 `update:modelValue`
// 但在 Vue 2 中,你仍然可以使用 `value`
props: ['modelValue'], // Vue 3 推荐命名
// 或者在 Vue 2 中
// props: ['value'],
}
</script>
注意
- 在 Vue 3 中,推荐的做法是使用
modelValue
作为 prop 和update:modelValue
作为事件,以更清晰地表达这是与v-model
绑定的值。然而,Vue 3 仍然支持使用value
作为 prop,但建议遵循新的命名约定。 - 在 Vue 2.2.0 及以上版本中,
.sync
修饰符提供了一种简化的方式来更新父组件的状态,但它不是v-model
的直接替代品。.sync
修饰符允许你以update:propName
的形式监听任何 prop 的变化。
通过上面的方式,你可以在 Vue.js 的自定义组件中监听原生事件,并更新父组件中通过 v-model
绑定的数据。