前言
如果您是一名React开发者,您应该了解在开发React项目的过程中,如果遇到了处理表单的数据的时候一般有俩种的选择方式,一种是选择受控组件,一种是选择非受控组件。那么我们该如何正确的选择使用它们呢?
您可能已经看过很多文章说“不应该使用setState”,而文档又声称“ refs不好” ……这在马克思主义基本原理里面这就是矛盾的体现,我们到底该如何选择呢?
带着问题看文章
- 你应该怎么做表单?
- 什么时候适合用受控组件,什么时候适合用非受控组件
接下来开始我们的文章正题:
非受控组件:
非受控组件其实就是传统的HTML表单
function Index(props) {
return (
<div>
<input type="text" />
</div>
)
}
html的input元素会帮你记住你的输入内容,然后我们就可以通过他们的ref获取值。或者在你输入内容的时候追加一个onChange通过event获取值。
但是一般如果你想要使用onChange获取值笔者就不建议使用非受控组件了。
现在我们在上面的代码中追加一个button与一个事件处理程序:
import React, { useRef } from 'react';
function Index(props) {
const inputRef = useRef();
function handleSubmitClick() {
const value = inputRef.current.value;
// do something with 'value'
}
return (
<div>
<input
type="text"
ref={inputRef}
/>
<button
onClick={handleSubmitClick}
>
获取值!
</button>
</div>
)
}
这样我们就可以通过获取到input的输入值了,我们就可以进行一些表单的提交操作之类的。
不受控组件的优点就是代码量会小一些,使用起来也很简单。
缺点就是很弱。。。为什么说它很弱?请看下面的受控组件。
受控组件:
受控组件一般就是我们控制输入框的value值与onChang:
import React, { useState } from 'react';
function Index(props) {
const [inputVal, setInputValue] = useState('');
function handleSubmitClick() {
console.log(inputVal)
// do something with 'inputVal'
}
return (
<div>
<input
type="text"
value={inputVal}
onChange={event => setInputValue(event.target.value)}
/>
<button
onClick={handleSubmitClick}
>
获取值!
</button>
</div>
)
}
上面的代码通过给input手动设置value的方法使他受我们的控制,然后在绑定一个onChange事件,获取event对象的.target.value的值。设置给我们的state。这样就实现了我们的数据双向绑定。
很多朋友就会很好奇,这样来看的话受控组件比非受控组件麻烦多了啊,我们为什么要用受控组件?
笔者刚刚也提了一下,代码确实是非受控组件的代码更少,但是它没有受控组件强!
比如我们想要限制用户的输入内容,并对其进行处理显示。
现在我们将用户输入的所有位置的空格去掉:
import React, { useState } from 'react';
function Index(props) {
const [inputVal, setInputValue] = useState('');
function handleSubmitClick() {
console.log(inputVal)
// do something with 'inputVal'
}
return (
<div>
<input
type="text"
value={inputVal}
onChange={event => setInputValue(event.target.value.replace(/\s/g, ''))}
/>
<button
onClick={handleSubmitClick}
>
获取值!
</button>
</div>
)
}
当然,将它变成受控组件的好处远不止如此。
我们还可以将俩个或以上的input的值去进行绑定相关联。
比如我们现在做俩个input标签,我在一个input里输入会影响另外一个的值。
比如我们设置俩个input输入框的总和值为100。
import React, { useState } from 'react';
function Children(props) {
const maxValue = 100;
const [input1Val, setInput1Value] = useState(0);
const [input2Val, setInput2Value] = useState(100);
function inputChange({ key, value}) {
let newValue = `${value}`.replace(/^0/g, '');
!newValue
? newValue = 0
: newValue > maxValue
? newValue = maxValue
: newValue < 0
? newValue = 0
: newValue = newValue;
newValue = parseFloat(newValue);
eval(`(() => setInput${key}Value(${newValue}))()`.toString());
eval(`(() => setInput${key === 1 ? 2 : 1}Value(${maxValue - newValue}))()`.toString());
// 如果你不想要eval解析你可以将上面俩行代码去掉,替换为下方的:
// if (key === 1) {
// setInput1Value(newValue);
// setInput2Value(maxValue - newValue);
// } else {
// setInput2Value(newValue);
// setInput1Value(maxValue - newValue);
// }
}
const inputOptions = {
type: 'number',
max: 100,
min: 0,
};
return (
<div>
<input
value={input1Val}
onChange={event => inputChange({ key: 1, value: event.target.value })}
{...inputOptions}
/>
+
<input
value={input2Val}
onChange={event => inputChange({ key: 2, value: event.target.value })}
{...inputOptions}
/>
= {maxValue}
</div>
)
}
上方代码我们不仅更改了value的显示【比如输入大于100的时候会把它改为100,输入小于0的时候会改为0】。而且我们也实现了双输入框数据的关联性。
受控组件强的地方:
1.可以自己控制数据。在改变数据的时候做一些我们想要进行的操作。【非受控组件也可以,就是比受控组件麻烦】
2.我们可以实时验证数据。
3.做一些我们想要的关联关系处理。
。。。
想要将元素变为受控组件可以给元素增加如下属性:
小总结
其实笔者认为受控组件与非受控组件各有优处。如果你的需求很简单,不需要什么认证之类的话就用非受控组件即可,如果需求略微复杂还是建议使用受控组件。
当然,就算你最开始使用的是非受控组件,后面想要改成受控组件也是很简单的。就参照受控组件内容里最下方的那个表格加入该有的属性和方法即可~