前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Vue v-model 自定义组件
VuVue组件与模板

Vue 中子组件如何支持 v-model,默认的 prop 名和事件名是什么?

组件上的 v-model 是一对单向接口的简写:值由父级传下,更新意图由子级发回。

前端进阶之旅 · 一题精讲更新于 2026.09.06
Vue#组件与模板#表单
先看核心答案读代码示例
理解线索

一次输入更新的单向闭环

  1. 父传当前值modelValue 表达唯一可信状态
  2. 子发更新意图update:modelValue 携带候选新值
  3. 父写回状态下一轮渲染把已接受的值再次传下

语法看似双向,数据所有权仍然是父到子、事件子到父的两个单向步骤。

核心回答

先记住这个答案

Vue 3 中不带参数的组件 v-model 默认展开为 modelValue prop 和 update:modelValue 事件。子组件读取 props.modelValue 渲染当前值,在用户输入时 emit("update:modelValue", nextValue);父组件监听事件并更新自己的状态,再把新值传回。子组件不应直接修改 prop,因为状态所有权仍在父级。这个模式可以看作受控组件契约:是否接受、规范化或撤销新值由父级决定。defineModel 是 Vue 3.4+ 对同一契约的编译期简写。

  • 默认 prop 是 modelValue
  • 默认事件是 update:modelValue
  • 父级仍拥有最终状态

语法糖背后是公开接口

<TextField v-model="name" /> 等价于传入 :model-value="name" 并监听 @update:model-value 后执行 name = $event。理解展开结果后,校验失败、延迟提交和只读模式都能落在明确边界,而不是让子组件偷偷改父状态。

事件必须携带完整候选值。只发送“changed”让父级再读取子实例,会破坏单向契约并增加时序耦合。对象值还要决定是发送新对象还是结构化变更,避免子级直接原地修改共享引用。

手写 modelValue 与更新事件

下例把输入节点的 value 绑定到 prop,原生 input 事件发生时提取字符串并通知父级。父级可以在监听器中去空格、拒绝非法值或写入 store,再通过下一次 prop 更新控制最终显示。

测试应断言两个方向:父级改变 modelValue 后子节点显示新值;触发输入后只发出一次正确载荷,并由父级更新后才改变受控状态。只断言 DOM 事件触发不足以验证组件契约。

显式实现单个 v-modelTypeScript
import { defineComponent, h } from 'vue'

const TextField = defineComponent({
  props: { modelValue: { type: String, required: true } },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    return () => h('input', {
      value: props.modelValue,
      onInput: (event: Event) => {
        emit('update:modelValue', (event.target as HTMLInputElement).value)
      }
    })
  }
})

组件只读取 prop 并发送候选字符串。父级模板使用 <TextField v-model="name" /> 即可连接这两个接口,状态更新策略仍由父级决定。

更新频率应匹配产品语义

文本输入通常每次 input 就更新,昂贵搜索可以在父级防抖,金额或复杂对象则可能采用草稿与提交两个事件。不要为了性能改变 v-model 契约却不告诉调用方,否则外部看到的 value 与内部显示会长期分叉。

发送与当前值相同的更新通常没有必要,父级响应式系统也可能跳过等值更新。需要记录用户动作时应另发语义事件,例如 submit 或 blur,不能把状态更新次数当作完整行为日志。

回答前,多想一步

容易答错的地方

在子组件内直接修改 modelValue
prop 是只读输入,直接写会告警且破坏父级所有权。需要本地草稿时创建独立 ref,并明确何时同步外部变化、何时提交。
把事件写成 update:model-value
契约的脚本名称是 update:modelValue;模板监听可以使用 @update:model-value。声明、emit 与类型定义应使用同一个完整事件名。
试着用自己的话回答

面试官还会怎么问?

本地输入草稿怎样避免覆盖外部更新?

先定义冲突规则:未编辑时跟随 prop,编辑中保留草稿或提示版本变化,提交后 emit 完整值。不能用一个无条件 watch 双向复制,否则容易形成覆盖和循环。

v-model 可以传对象吗?

可以,但子级不要原地修改来自父级的对象。发送结构共享可控的新对象,或设计字段级事件,并考虑深层比较与验证成本。

defineModel 改变运行时契约吗?

不会,它在编译期生成对应 prop 与更新事件,并给 setup 返回可读写 ref。版本和默认值同步等边界仍需理解。

从一道题,走向一组知识

把知识连起来

组件与模板

Vue 3 中一个组件如何实现多个 v-model 绑定?

多个字段可以用带参数的 v-model 拆成独立契约。

组件与模板

如何在 Vue 自定义组件的 v-model 上支持自定义修饰符?

组件可读取修饰符并规范化候选值。

组件与模板

Vue 中自定义事件名推荐用什么大小写形式,模板中监听时如何对应?

update:modelValue 也是组件事件,脚本与模板有对应写法。

参考资料

  • Vue:组件 v-model
  • Vue:props 单向数据流

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 语法糖背后是公开接口
  3. 手写 modelValue 与更新事件
  4. 更新频率应匹配产品语义
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑