首先我们要明白什么时候要获取表单数据——当表单项发生变化时。
以下面的表单为例说明:
<form onSubmit={formSubmitHandler}>
<div className="form-item">
<label htmlFor="date">日期</label>
<input onChange={dateChangeHandler} id="date" type="date"/>
</div>
<div className="form-item">
<label htmlFor="desc">内容</label>
<input onChange={descChangeHandler} id="desc" type="text"/>
</div>
<div className="form-item">
<label htmlFor="time">时长</label>
<input onChange={timeChangeHandler} id="time" type="number"/>
</div>
<div className="form-btn">
<button>添加</button>
</div>
</form>
第一种原始DOM方法
const descChangeHandler = () => {
console.log("DOM方式获取: ", document.getElementById('desc').value);
};
第二种使用useRef
似乎好像也没简便多少。
const descRef = useRef();
const descChangeHandler = () => {
console.log("useRef获取: ", descRef.current.value);
};
第三种原生事件对象(推荐)
// 监听内容的变化
const descChangeHandler = (e) => {
// 获取到当前触发事件的对象 e;e 中保存了当前事件触发时的所有信息
// event.target 执行的是触发事件的对象(DOM对象)
console.log(e.target.value);
};
表单项数据填好后,需要汇总再提交至服务器。
<form onSubmit={formSubmitHandler}>
......
</form>
通过监听表单onSubmit方法来提交,而通常表单不需要自行提交,由react帮你提交(异步)。
// 创建三个变量,用来存储表单中的数据
let inputDate = ''; // 日期
let inputDesc = ''; // 描述
let inputTime = 0; // 时长
然后分别在input框绑定的监听函数中通过事件对象赋值对应的输入值value。
const formSubmitHandler = (e) => {
// 取消表单的默认行为
e.preventDefault();
// 获取表单项中的数据日期、内容、时长
// 将数据组装为一个对象
const newLog = {
date: new Date(inputDate),
desc: inputDesc,
time: +inputTime
};
console.log(newLog);
};
问题:表单提交成功,如何清空/重置表单项的旧数据?
非受控组件:说白了,就是只能通过DOM操作的表单元素。
受控组件:表单项的value受到react的state的控制管理(类似Vue中的v-model)。
我们可以将表单中的数据存储到state中,然后将state的数据设置为表单项value值。
将非受控组件元素交由state管理:
const [inputDate, setInputDate] = useState('');
const [inputDesc, setInputDesc] = useState('');
const [inputTime, setInputTime] = useState('');
<input onChange={dateChangeHandler} value={inputDate} id="date" type="date"/>
<input onChange={descChangeHandler} value={inputDesc} id="desc" type="text"/>
<input onChange={timeChangeHandler} value={inputTime} id="time" type="number"/>
然后再在监听函数中调用setXXX方法获取用户输入,当表单项发生变化,state会随之变化; 反之,state发生变化,表单项也会跟着改变,这种操作称为双向绑定(个人感觉v-model真香)。
如此一来,表单就成为了一个受控组件了。
另外我们也可以将表单数据集中到一个state中:
const [formData, setFormData] = useState({
inputDate:'',
inputDesc:'',
inputTime:''
});
监听函数的setXXX需改写成对象展开形式:
setFormData({
...formData,
inputDate: e.target.value
});
当然还可以再精简点,这里可以只用一个函数来监听所有的input元素,给每个input设置id,通过id和保存的数据的属性名一样就可以。