React表单

受控组件

  • 标签 input、textarea、select的值的改变通常是根据用户输入进行更新。在React中,可变状态通常保存在组件的状态属性中,并且只能使用 setState() 更新,而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称为:“受控组件”。

不受控组件

  • 在受控组件中,表单数据由 React 组件负责处理。另外一个选择是不受控组件,其表单数据由 DOM 元素本身处理。。

处理多个输入元素

  • 当您需要处理多个受控的 input 元素时,您可以为每个元素添加一个 name 属性,并且让处理函数根据 event.target.name 的值来选择要做什么。


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .item{
            margin:10px;
        }
    </style>
</head>

<body>
    <div id="root"></div>
</body>

</html>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
class NameForm extends React.Component {
     constructor(props) {
        super(props);
        this.state = {
            username: '',
            password: '',
            selections: 'strawberry',
            sex: '0',
            hobby: [
                {
                    'title': "睡觉",
                    'checked': false,
                },
                {
                    'title': "吃饭",
                    'checked': false
                },
                {
                    'title': "敲代码",
                    'checked': false
                }
            ],
            avatar:null,
            avatarCDN:'',
        }
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);

        //  使用 ref 来从 DOM 节点中获取表单数据。
        // this.files = React.createRef()

    }

    // 批量修改受控组件的值
    handleChange(event) {
        const target = event.target
        const name = target.name
        // setState() 自动将部分状态合并到当前状态
        this.setState({
            [name]: target.value
        })
    }

    changeHobby(key) {
        var hobby = this.state.hobby
        hobby[key].checked = !hobby[key].checked
        this.setState({
            hobby:hobby
        })
    }

    handleSubmit(event) {
        event.preventDefault();
        console.log(this.state)
        // 获取上传文件的内容
        // console.log(this.files.current.files)

    }

    avatar = (e) => 
    {
        var avatar = e.target.files[0]

        var avatarCDN = URL.createObjectURL(avatar)

        this.setState({
            avatar:avatar,
            avatarCDN:avatarCDN
        })
    }

    render() {
        let preview = ''

        if(this.state.avatarCDN)
        {
            preview = <img src={this.state.avatarCDN} />
        }
        return (
            <div>
                <form onSubmit={this.handleSubmit}>
                    <div style={{ margin: '10px' }}>
                        <label>
                            名字:
                            <input type="text" name="username" value={this.state.username} onChange={this.handleChange} />
                        </label>
                    </div>
                    <div style={{ margin: '10px' }}>
                        <label>
                            密码:
                            <input type="password" name="password" value={this.state.password} onChange={this.handleChange} />
                        </label>
                    </div>
                    <div style={{ margin: '10px' }}>
                        <label>
                            选择你喜欢的水果:
                            <select name="selections" value={this.state.selections} onChange={this.handleChange}>
                                <option value="grapefruit">葡萄柚</option>
                                <option value="lime">橙子</option>
                                <option value="strawberry">草莓</option>
                                <option value="banana">香蕉</option>
                                <option value="mango">芒果</option>
                            </select>
                        </label>
                    </div>
                    <div style={{ margin: '10px' }}>
                        <label>
                            文件:
                            {/* <input type="file" ref={this.files} multiple="multiple" /> */}

                            <input type="file" name="avatar" onChange={this.avatar} /><br />

                            {preview}<br />

                        </label>
                    </div>
                    <div style={{ margin: '10px' }}>
                        <label>
                            性别:
                            <input type="radio" name="sex" value="0" checked={this.state.sex == '0'} onChange={this.handleChange} /> 保密
                            <input type="radio" name="sex" value="1" checked={this.state.sex == '1'} onChange={this.handleChange} /><input type="radio" name="sex" value="2" checked={this.state.sex == '2'} onChange={this.handleChange} /></label>
                    </div>
                    <div style={{ margin: '10px' }}>
                        <label>
                            爱好:
                            {
                                this.state.hobby.map((item, index) => {
                                    return (
                                        <span key={index}>
                                            <input type="checkbox" checked={item.checked} onChange={this.changeHobby.bind(this, index)} />
                                            {item.title}
                                        </span>
                                    )
                                })
                            }
                        </label>
                    </div>
                    <div style={{ margin: '10px' }}>
                        <input type="submit" value="提交" />
                    </div>
                </form>
            </div>
        )
    }
}


var vm = ReactDOM.render(
    <NameForm />,
    document.getElementById("root")
  );
</script>
powered by GitbookEdit Time: 2023-04-08 10:28:32