每天学点React - 受控组件与非受控组件

73 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

受控组件与非受控组件

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

受控组件

页面中,所有输入类的DOM,随着用户的输入,将值维护到状态中去,等需要用到的时候再到状态中获取,这就属于受控组件。

<!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>


    <!-- 设置类型为babel -->
    <script type="text/babel">
        class LoginInfo extends React.Component {

            // 初始化状态
            state = {
                username: '',
                password: ''
            }

            handlerSubmit = (event) => {
                // 阻止表单提交
                event.preventDefault()
                const {username, password} = this.state
                alert('用户名:' + username + `\n` + '密码:' + password)
            }

            // 更新username
            usernameChange = (event) => {
                this.setState({username: event.target.value})
            }

            // 更新password
            passwordChange = (event) => {
                this.setState({password: event.target.value})
            }

            render() {
                return (
                    <form action="http://www.baidu.com" onSubmit={this.handlerSubmit}>
                        用户名:<input onChange={this.usernameChange} type="text" name="username" />
                        密码:<input onChange={this.passwordChange} type="password" name="password" />
                        <button>登陆</button>
                    </form>
                )
            }
        }

        ReactDOM.render(<LoginInfo />, document.getElementById("test"))
    </script>
</body>

</html>

image.png

非受控组件

页面中所有输入类的DOM,现用现取,都是非受控组件

例如:登陆账号时,输入的用户名密码,在点击登陆按钮之后才去获取这两个输入框的值。

<!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>非受控组件</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>


    <!-- 设置类型为babel -->
    <script type="text/babel">
        class LoginInfo extends React.Component{
            render(){
                return(
                    <form action="https://www.baidu.com"  onSubmit={this.handlerSubmit}>
                        用户名:<input ref={c => this.username = c} type="text" name="username"/>    
                        密码:<input ref={c => this.password = c} type="password" name="password"/>   
                        <button>登陆</button> 
                    </form>
                )
            }

            handlerSubmit = (event) => {
                // 阻止表单提交
                event.preventDefault()
                const {username, password} = this
                alert('用户名:' + username.value + `\n` + '密码:' + password.value)
            }
        }

        ReactDOM.render(<LoginInfo/>, document.getElementById("test"))
    </script>
</body>
</html>

小结

受控组件相较于非受控组件,可以省略ref的定义,再React官网中有建议尽量少的去定义ref,所以,在可能的情况下,我们需要更倾向于受控组件的实现。