跳转到内容

受控表单与 v-model

两个表单都实时展示姓名和方向。React 把输入值保持在 state 中,Vue 通过 v-model 把表单控件与 ref 连接起来。

React

用 value 和 onChange 显式实现受控表单。

在线预览

实时 state

小明

正在学习:React

已保存:0

组件关系与数据流

Form StateComponentBindingDOM Control

差异焦点读取、更新和回写都是显式代码,state 是唯一数据源。

实线表示依赖、数据或命令传递,虚线表示事件、回调或清理路径。

flowchart TB
  accTitle: React 受控表单数据流
  accDescr: input 事件读取 DOM value,onChange 调用 setter 更新 state,组件重新渲染后再通过 value prop 把状态写回表单控件。
  input[("input / select DOM")] -.->|"onChange event"| handler{{"读取 event.target.value"}}
  handler --> setter{{"调用 setter"}}
  setter --> state(["name / direction state"])
  state --> demo["ReactDemo render"]
  demo -->|"value prop"| input
  class state state
  class demo component
  class handler,setter process
  class input resource
  classDef state fill:#ffffff,stroke:#149eca,color:#172033,stroke-width:1.2px
  classDef component fill:#e5f6fb,stroke:#149eca,color:#172033,stroke-width:2px,font-weight:600
  classDef process fill:#f4fbfd,stroke:#149eca,color:#172033,stroke-width:1.6px
  classDef resource fill:#f3f5f8,stroke:#778195,color:#172033,stroke-width:1.4px

事件把 DOM 值提交给 state,下一次 render 再用 value prop 控制表单。

React 流程图
React 组件关系与数据流

滚轮缩放 · 按住拖动 · 双击重置 · Esc 关闭

实际运行源码

import { useState } from "react";
import type { FormEvent } from "react";
export function ReactDemo() {
const [name, setName] = useState("小明");
const [direction, setDirection] = useState("React");
const [submitted, setSubmitted] = useState(0);
function submit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setSubmitted((current) => current + 1);
}
return (
<div className="demo-stack">
<form className="demo-form" onSubmit={submit}>
<label className="demo-field">
姓名
<input
className="demo-input"
value={name}
onChange={(event) => setName(event.target.value)}
/>
</label>
<label className="demo-field">
学习方向
<select
className="demo-select"
value={direction}
onChange={(event) => setDirection(event.target.value)}
>
<option>React</option>
<option>Vue</option>
<option>两者对比</option>
</select>
</label>
<button className="demo-button" type="submit">
保存资料
</button>
</form>
<div className="demo-card">
<span className="demo-tag">实时 state</span>
<h2>{name || "未填写姓名"}</h2>
<p>正在学习:{direction}</p>
<p>已保存:{submitted} 次</p>
</div>
</div>
);
}
Vue 3

用 v-model 连接表单控件与响应式 ref。

在线预览

实时 ref

小明

正在学习:Vue

已保存:0 次

组件关系与数据流

Form StateComponentBindingDOM Control

差异焦点模板只声明绑定目标,事件读取和属性回写由编译结果完成。

实线表示依赖、数据或命令传递,虚线表示事件、回调或清理路径。

flowchart TB
  accTitle: Vue v-model 表单双向绑定
  accDescr: v-model 编译为表单属性绑定和更新事件,用户输入时写入 ref,响应式更新又把最新值同步到表单与预览模板。
  input[("input / select DOM")] <--> model{{"v-model 编译绑定"}}
  model <--> state(["name / direction refs"])
  state --> trigger{{"响应式依赖更新"}}
  trigger --> template["表单 + 预览模板"]
  class state state
  class template component
  class model,trigger process
  class input resource
  classDef state fill:#ffffff,stroke:#42b883,color:#172033,stroke-width:1.2px
  classDef component fill:#e7f8f0,stroke:#42b883,color:#172033,stroke-width:2px,font-weight:600
  classDef process fill:#f2fbf7,stroke:#42b883,color:#172033,stroke-width:1.6px
  classDef resource fill:#f3f5f8,stroke:#778195,color:#172033,stroke-width:1.4px

v-model 组合属性绑定和更新事件,把 DOM 控件与响应式 ref 连接起来。

Vue 3 流程图
Vue 3 组件关系与数据流

滚轮缩放 · 按住拖动 · 双击重置 · Esc 关闭

实际运行源码

<script setup lang="ts">
import { ref } from "vue";
const name = ref("小明");
const direction = ref("Vue");
const submitted = ref(0);
function submit() {
submitted.value += 1;
}
</script>
<template>
<div class="demo-stack">
<form class="demo-form" @submit.prevent="submit">
<label class="demo-field">
姓名
<input v-model="name" class="demo-input" />
</label>
<label class="demo-field">
学习方向
<select v-model="direction" class="demo-select">
<option>React</option>
<option>Vue</option>
<option>两者对比</option>
</select>
</label>
<button class="demo-button" type="submit">保存资料</button>
</form>
<div class="demo-card">
<span class="demo-tag">实时 ref</span>
<h2>{{ name || "未填写姓名" }}</h2>
<p>正在学习:{{ direction }}</p>
<p>已保存:{{ submitted }} 次</p>
</div>
</div>
</template>