# 表单数据收集

## 非受控组件

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
<script type="text/babel">
    //创建组件
    class Login extends React.Component {
        handleSubmit = (event) => {
            event.preventDefault() //阻止表单提交
            const {username, password} = this
            alert(`你输入的用户名是：${username.value},你输入的密码是：${password.value}`)
        }

        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>
            )
        }
    }

    ReactDOM.render(<Login />, document.getElementById("app"))
</script>
</body>
</html>
```

## 受控组件（类似双向绑定）

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
<script type="text/babel">
    //创建组件
    class Login extends React.Component{

        //初始化状态
        state = {
            username:'', //用户名
            password:'' //密码
        }

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

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

        //表单提交的回调
        handleSubmit = (event)=>{
            event.preventDefault() //阻止表单提交
            const {username,password} = this.state
            alert(`你输入的用户名是：${username},你输入的密码是：${password}`)
        }

        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("app"))
</script>
</body>
</html>
```

## 优化：高阶函数柯里化

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
<script type="text/babel">
    //#region
    /*
        高阶函数：如果一个函数符合下面2个规范中的任何一个，那该函数就是高阶函数。
                        1.若A函数，接收的参数是一个函数，那么A就可以称之为高阶函数。
                        2.若A函数，调用的返回值依然是一个函数，那么A就可以称之为高阶函数。
                        常见的高阶函数有：Promise、setTimeout、arr.map()等等

        函数的柯里化：通过函数调用继续返回函数的方式，实现多次接收参数最后统一处理的函数编码形式。
            function sum(a){
                return(b)=>{
                    return (c)=>{
                        return a+b+c
                    }
                }
            }
        */
    //#endregion
    //创建组件
    class Login extends React.Component{
        //初始化状态
        state = {
            username:'', //用户名
            password:'' //密码
        }

        //保存表单数据到状态中
        saveFormData = (dataType)=>{
            return (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={this.saveFormData('username')} type="text" name="username"/>
                    密码：<input onChange={this.saveFormData('password')} type="password" name="password"/>
                    <button>登录</button>
                </form>
            )
        }
    }

    ReactDOM.render(<Login />, document.getElementById("app"))
</script>
</body>
</html>
```

## 不用函数柯里化实现：箭头实现

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="app"></div>

<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.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("app"))
</script>
</body>
</html>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yangsx95.gitbook.io/notes/front-end/react/biao-dan-shu-ju-shou-ji.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
