【08】基础知识:React中收集表单数据(非受控组件和受控组件)

一、概念

非受控组件:

页面中所有输入类的 DOM,现用现取。

给组件绑定 ref 属性,在需要时通过 ref 获取相应值。

受控组件:

页面中所有输入类的 DOM,随着输入,将内容维护到状态 state中,当需要使用时,直接从 state 中读取,这类 DOM属于受控组件。

通过组件的 onChange 事件,获取组件的 value 值,存储到 state 中。

相当于 VUE 中的双向数据绑定 v-model,React 中没有封装双向数据绑定,需要自己实现。

二、案例

需求:定义一个包含表单的组件,输入用户名密码后,点击登录提示输入信息

非受控实现

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>1_非受控组件</title>
</head>
<body>
	<!-- 准备好一个"容器" -->
	<div id="test"></div>
	
	<!-- 引入react核心库 -->
	<script type="text/javascript" src="../js/react.development.js"></script>
	<!-- 引入react-dom,用于支持react操作DOM -->
	<script type="text/javascript" src="../js/react-dom.development.js"></script>
	<!-- 引入babel,用于将jsx转为js -->
	<script type="text/javascript" src="../js/babel.min.js"></script>

	<script type="text/babel">
		class Login extends React.Component {
			render() {
				return (
					<form onSubmit={this.handleSubmit}>
						用户名:<input ref={c => this.username = c} type="text" name="username"/>
						<input ref={c => this.password = c} type="password" name="password"/>
						密码:<button>登录</button>
					</form>
				)
			}

			handleSubmit = event => {
				event.preventDefault() // 阻止表单提交,form中的button默认也是onSubmit方法
				const { username, password } = this
				alert(`你输入的用户名是${username.value},密码是${password.value}`)
			}
		}

		ReactDOM.render(<Login/>, document.getElementById('test'))
	</script>
</body>
</html>

受控实现

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>2_受控组件</title>
</head>
<body>
	<!-- 准备好一个"容器" -->
	<div id="test"></div>
	
	<!-- 引入react核心库 -->
	<script type="text/javascript" src="../js/react.development.js"></script>
	<!-- 引入react-dom,用于支持react操作DOM -->
	<script type="text/javascript" src="../js/react-dom.development.js"></script>
	<!-- 引入babel,用于将jsx转为js -->
	<script type="text/javascript" src="../js/babel.min.js"></script>

	<script type="text/babel">
		class Login extends React.Component {
			// 初始化状态
			state = {
				username: '', // 用户名
				password: '' // 密码
			}

			// 提交
			handleSubmit = event => {
				event.preventDefault() // 阻止表单提交,form中的button默认也是onSubmit方法
				const { username, password } = this.state
				alert(`你输入的用户名是${username},密码是${password}`)
			}

			// 保存用户名到状态中
			saveUsername = event => {
				this.setState({ username: event.target.value})
			}

			// 保存密码到状态中
			savePassword = event=>{
				this.setState({ password: event.target.value })
			}


			render() {
				return (
					<form onSubmit={this.handleSubmit}>
						用户名:<input onChange={this.saveUsername} type="text" name="username"/>
						<input onChange={this.savePassword} type="password" name="password"/>
						密码:<button>登录</button>
					</form>
				)
			}
		}

		// 渲染组件
		ReactDOM.render(<Login/>, document.getElementById('test'))
	</script>
</body>
</html>

三、高阶写法

高阶函数 + 函数柯里化

高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。

1、若 A 函数,接收的参数是一个函数,那么 A 就可以称之为高阶函数。

2、若 A 函数,调用的返回值依然是一个函数,那么 A 就可以称之为高阶函数。

常见的高阶函数有:Promise、setTimeout、arr.map() 等等

函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。

复制代码
function sum(a) {
	return(b) => {
		return (c) => {
			return a+b+c
		}
	}
}
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>高阶函数_函数柯里化</title>
</head>
<body>
	<!-- 准备好一个"容器" -->
	<div id="test"></div>

	<!-- 引入react核心库 -->
	<script type="text/javascript" src="../js/react.development.js"></script>
	<!-- 引入react-dom,用于支持react操作DOM -->
	<script type="text/javascript" src="../js/react-dom.development.js"></script>
	<!-- 引入babel,用于将jsx转为js -->
	<script type="text/javascript" src="../js/babel.min.js"></script>

	<script type="text/babel">
		// 创建组件
		class Login extends React.Component {
			// 初始化状态
			state = {
				username: '', //用户名
				password: '' //密码
			}

			// 保存表单数据到状态中
			saveFormData = dataType => {
				return event => {
					this.setState({ [dataType]: event.target.value })
				}
			}

			// 表单提交的回调
			handleSubmit = event => {
				event.preventDefault() // 阻止表单提交,form中的button默认也是onSubmit方法
				const { username, password } = this.state
				alert(`你输入的用户名是${username},密码是${password}`)
			}

			render() {
				return (
					<form onSubmit={this.handleSubmit}>
						用户名:<input onChange={this.saveFormData('username')} type="text" name="username" />
						密码:<input onChange={this.saveFormData('password')} type="password" name="password" />
						<button>登录</button>
					</form>
				)
			}
		}
		// 渲染组件
		ReactDOM.render(<Login />, document.getElementById('test'))
	</script>
</body>

</html>

使用箭头函数

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>2_不用函数柯里化的实现</title>
</head>

<body>
	<!-- 准备好一个"容器" -->
	<div id="test"></div>

	<!-- 引入react核心库 -->
	<script type="text/javascript" src="../js/react.development.js"></script>
	<!-- 引入react-dom,用于支持react操作DOM -->
	<script type="text/javascript" src="../js/react-dom.development.js"></script>
	<!-- 引入babel,用于将jsx转为js -->
	<script type="text/javascript" src="../js/babel.min.js"></script>

	<script type="text/babel">
		// 创建组件
		class Login extends React.Component {
			// 初始化状态
			state = {
				username: '', //用户名
				password: '' //密码
			}

			// 保存表单数据到状态中
			saveFormData = (dataType, event) => {
				this.setState({ [dataType]: event.target.value })
			}

			// 表单提交的回调
			handleSubmit = (event) => {
				event.preventDefault() //阻止表单提交
				const { username, password } = this.state
				alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
			}
			render() {
				return (
					<form onSubmit={this.handleSubmit}>
						用户名:<input onChange={event => this.saveFormData('username', event)} type="text" name="username" />
						密码:<input onChange={event => this.saveFormData('password', event)} type="password" name="password" />
						<button>登录</button>
					</form>
				)
			}
		}
		// 渲染组件
		ReactDOM.render(<Login />, document.getElementById('test'))
	</script>
</body>
</html>
相关推荐
腾讯TNTWeb前端团队29 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom5 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom5 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom6 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom6 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试