标准答案

  1. Vue 2 默认 v-model 对组件使用 value 作为 prop,input 作为更新事件。组件可以通过 model 选项改成其它 prop 和 event。
  2. Vue 2 的 .sync 常用于 prop 的双向更新,本质是监听 update:propName 事件后更新父组件状态。
  3. Vue 3 默认 v-model 使用 modelValue 和 update:modelValue,写法更统一。
  4. Vue 3 支持多个 v-model,例如 v-model:title、v-model:visible,每个对应一个 prop 和 update 事件。
  5. 迁移时要检查组件库 API。Vue 2 的 value/input、visible.sync、model 选项,通常要改成 Vue 3 的 modelValue/update:modelValue 或具名 v-model。

题目解析

这题的关键是把 v-model 拆成 prop 和 event。双向绑定不是魔法,只是父组件传值、子组件发事件。

Vue 3 多 v-model 让复杂表单组件、弹窗组件和筛选组件的接口更清楚。

Vue 2 的 .sync 在 Vue 3 中不再作为主要写法,应该用具名 v-model 或显式事件表达。

代码示例

下面是 Vue 3 中默认 v-model 和具名 v-model 的组件接口。

Vue
<!-- BaseDialog.vue -->
<script setup lang="ts">
defineProps<{
  visible: boolean
  title: string
}>()

const emit = defineEmits<{
  'update:visible': [value: boolean]
  'update:title': [value: string]
}>()
</script>

<template>
  <dialog :open="visible">
    <input
      :value="title"
      @input="emit('update:title', ($event.target as HTMLInputElement).value)"
    >
    <button type="button" @click="emit('update:visible', false)">
      关闭
    </button>
  </dialog>
</template>
Vue
<BaseDialog
  v-model:visible="dialogVisible"
  v-model:title="dialogTitle"
/>

常见误区

  • 只会背 v-model,不知道它背后是 prop 和 update 事件。
  • 迁移 Vue 2 组件时继续使用 value/input,导致父组件 v-model 不生效。
  • 复杂组件只塞一个 modelValue,多个状态含义混在一起。

作者信息