React学习:表单(Forms)
受控组件(Controlled Components)
- 在 HTML 中,表单元素如 < input>,< textarea> 和 < select> 表单元素通常保持自己的状态,并根据用户输入进行更新。
- 在 React 中,可变状态一般保存在组件的 state(状态) 属性中,并且只能通过 setState() 更新。
我们可以通过使 React 的 state 成为 “单一数据源原则” 来结合这两个形式。然后渲染表单的 React 组件也可以控制在用户输入之后的行为。这种形式,其值由 React 控制的输入表单元素称为“受控组件”。
一、用value实现受控组件
总的来说,< input type=”text”>, < textarea> 和 < select> 工作方式都类似 —— 它们都接受一个 value 属性可以用来实现一个受控组件。
1、< input type=”text”/>
看下面例子:
由于 value 属性设置在我们的表单元素上,显示的值总是 this.state.value,以满足 state 状态的同一数据理念。 handleChange 在每次敲击键盘时运行,以更新 React state(状态),显示的值将更新为用户的输入。
class NameForm extends React.Component {constructor(props){super(props);this.state = {value:''};}handleChange = (e) => {this.setState({value: e.target.value});//这样是错的:this.setState(() => ({value:e.target.value }));}handleSubmit = (e) => {alert('input value is : ' + this.state.value);e.preventDefault();}render(){return();}
}ReactDOM.render( ,document.getElementById('root')
);
输出:
输入信息,点击’submit’
对于受控组件来说,每一次 state(状态) 变化都会伴有相关联的处理函数。这使得可以直接修改或验证用户的输入。比如,如果我们希望强制 name 的输入都是大写字母,可以这样来写 handleChange 方法:
//效果:在键盘输入任意字母,input里显示出来的是大写字母
handleChange(e) {this.setState({value: e.target.value.toUpperCase()});
}
2、< textare/>
在 HTML 中,< textarea> 元素通过它的子节点定义了它的文本值:
在 React 中,< textarea> 的赋值使用 value 属性替代。这样一来,表单中 < textarea> 的书写方式接近于单行文本输入框 :
例:
class EssayForm extends React.Component {constructor(props){super(props);this.state = {value:'Please write an essay'};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this); }handleChange(e){this.setState({value: e.target.value });}handleSubmit(e){alert('input value is : ' + this.state.value);e.preventDefault();}render(){return();}
}
输出:
修改完值后,点击’submit’,会弹出
3、< select/>
在 HTML 中,< select> 创建了一个下拉列表。例如,这段 HTML 创建一个下拉列表:
在React 中,并不使用这个 selected 属性,而是在根 select 标签中使用了一个 value 属性。这使得受控组件使用更方便,因为你只需要更新一处即可。
例:
class FlavorForm extends React.Component {constructor(props){super(props);this.state = {value: 'coconut'};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this); }handleChange(e){this.setState({value: e.target.value });}handleSubmit(e){alert('you selected value is : ' + this.state.value);e.preventDefault();}render(){return();}
}ReactDOM.render( ,document.getElementById('root')
);
效果:(默认coconut被选中)
选择‘mango’,点击‘submit’后,
注意:
您可以将一个数组传递给 value 属性,允许你在 select 标签中选择多个选项:
二、file input 标签
在HTML中, < input type=”file”> 可以让用户从设备存储器中选择一个或多个文件上传到服务器,或者通过 JavaScript 使用 File API 操作。
type="file" />
在 React 中, 和一个普通的 < input /> 类似,但有一个重要的区别:它是只读的(您不能以编程方式设置值)。相反,你应该使用 File API 与文件进行交互。
以下示例显示了如何使用一个 ref 来访问提交处理程序中的文件:
class FileInput extends React.Component {constructor(props) {super(props);this.handleSubmit = this.handleSubmit.bind(this);}handleSubmit(event) {event.preventDefault();alert(`Selected file - ${this.fileInput.files[0].name}`);}render() {return ();}
}ReactDOM.render( ,document.getElementById('root')
);
输出:
选择文件后,点击submit, 弹出文件名称
三、处理多个输入元素
当您需要处理多个受控的 input 元素时,您可以为每个元素添加一个 name 属性,并且让处理函数根据 event.target.name 的值来选择要做什么。
class Reservation extends React.Component {constructor(props) {super(props);this.state = {isGoing: true,numberOfGuests: 2};this.handleInputChange = this.handleInputChange.bind(this);}handleInputChange(event) {const target = event.target;const value = target.type === 'checkbox' ? target.checked : target.value;const name = target.name;this.setState({[name]: value});}render() {return ();}
}ReactDOM.render( ,document.getElementById('root')
);
输出效果:点击我
注意我们如何使用ES6计算的 属性名称语法 来更新与给定输入名称相对应的 state(状态) 键:
this.setState({[name]: value
});
这段代码等价于 ES5 代码:
var partialState = {};
partialState[name] = value;
this.setState(partialState);
四、受控 Input 组件的 null 值
官方文档是这么说的
其实意思就是
下面这段代码,不能编辑 input的值
ReactDOM.render(type='text' value="hi" />, document.getElementById('root')
);
但下面这段代码 可以编辑 input里的值
ReactDOM.render(type='text' value={null} />, document.getElementById('root'));
受控组件的替代方案:
有时使用受控组件有些乏味,因为你需要为每一个可更改的数据提供事件处理器,并通过 React 组件管理所有输入状态。当你将已经存在的代码转换为 React 时,或将 React 应用程序与非 React 库集成时,这可能变得特别烦人。在这些情况下,您可能需要使用不受控的组件,用于实现输入表单的替代技术。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
