• React学习笔记(三) 事件处理与表单元素


    一、事件处理

    1、事件处理

    React 元素的事件处理和 DOM 元素的相似,但是有一点语法上的不同,我们来看一个简单的例子

    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Demo</title>
        <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone"></script>
    </head>
    
    <body>
        <div id="app"></div>
    
        <script type="text/babel">
            class Counter extends React.Component {
                constructor(props) {
                    super(props);
                    this.state = { counter: 0 };
                    // 为事件处理函数绑定组件实例
                    // 绑定组件实例目的是为了能在事件处理函数中使用 this
                    this.handleClick = this.handleClick.bind(this);
                }
    
                handleClick(e) {
                    // 这里传入的 `e` 是一个合成事件
                    // 拥有与浏览器原生事件相同的接口,包括 stopPropagation() 和 preventDefault()
                    this.setState((state) => ({
                        counter: state.counter + 1
                    }));
                }
    
                render() {
                    return (
                        <div>
                            <p>{ this.state.counter }</p><br/>
                            {/*事件命名采用小驼峰式,而不是纯小写*/}
                            {/*传入一个函数作为事件处理函数,而不是一个字符串*/}
                            <button onClick={ this.handleClick }>加 1</button>
                        </div>
                    );
                }
            }
    
            ReactDOM.render(
                <Counter />,
                document.getElementById('app')
            );
        </script>
    </body>
    
    </html>
    

    2、this 绑定

    在上面的例子中,我们在 constructor() 中为事件处理函数绑定 this

    请注意,在 JavaScript 中,class 的方法默认是不会绑定 this 的,也就是说

    假如我们没有绑定 this.handleClick 并将其传入 onClick,那么当调用这个函数时,this 的值将为 undefined

    如果希望在事件处理函数中使用 this,那么为事件处理函数绑定 this 是必须的,方法有三种:

    (1)在构造函数中使用 bind

    class PrintThis extends React.Component {
        // 在构造函数中使用 `bind`
        constructor(props) {
            super(props)
            this.handleClick = this.handleClick.bind(this);
        }
    
        handleClick() {
            console.log(this)
        }
    
        render() {
            return (
                <button onClick={ this.handleClick }>Print This</button>
            );
        }
    }
    

    (2)在事件处理函数中使用 public class fields 语法

    class PrintThis extends React.Component {
        constructor(props) {
            super(props)
        }
    
        // 在事件处理函数中使用 `public class fields 语法`
        handleClick = () => {
            console.log(this)
        }
    
        render() {
            return (
                <button onClick={ this.handleClick }>Print This</button>
            );
        }
    }
    

    (3)在回调函数中使用 箭头函数

    class PrintThis extends React.Component {
        constructor(props) {
            super(props)
        }
    
        handleClick = () => {
            console.log(this)
        }
    
        render() {
            return (
                <div>
                	{/*在回调函数中使用 `箭头函数`*/}
                	<button onClick={ (e) => this.handleClick(e) }>Print This</button>
                </div>
            );
        }
    }
    

    3、传递参数

    有的时候,我们还需要给事件传递额外的参数

    class SayHello extends React.Component {
        // 事件处理函数接收的参数必须在合成事件 `e` 之前
        sayHelloTo(somebody, e) {
            alert('Hello ' + somebody);
        }
    
        render() {
            return (
                <div>
                    {/* 既可以使用 箭头函数 */}
                    <button onClick={ (e) => this.sayHelloTo('Alice', e) }>Say Hello To Alice</button>
                    {/* 也可以使用 Function.prototype.bind */}
                    <button onClick={ this.sayHelloTo.bind(this, 'Bob') }>Say Hello To Bob</button>
                </div>
            );
        }
    }
    

    二、表单元素

    1、受控组件

    在 HTML 中,表单元素通常自己维护状态,并且根据用户输入事件进行更新

    但是在 React 中,可变状态通常保存在组件的 state 属性中,并且只能通过 setState() 方法进行更新

    如果我们希望组件的 state 还是唯一数据源,同时还控制着用户输入事件,这样的组件我们称之为 受控组件

    class InfoForm extends React.Component {
        constructor(props) {
            super(props)
            this.state = { name: '', phone: '' } // 提供默认值
            this.handleChange = this.handleChange.bind(this)
            this.handleSubmit = this.handleSubmit.bind(this)
        }
    
        // 为用户事件(state 发生改变)定义处理函数
        handleChange(event) {
            // console.log(event.target)
            const target = event.target
            // 如果需要处理多个 input 元素,那么可以根据 `target.name` 执行不同的操作
            if (target.name === 'userName') {
                this.setState({ name: target.value })
            } else { // target.name === 'userPhone'
                this.setState({ phone: target.value })
            }
        }
    
        handleSubmit(event) {
            alert('您的名字是 ' + this.state.name + ';' + '您的手机是 ' + this.state.phone)
            event.preventDefault()
        }
    
        render() {
            return (
                // onSubmit 属性为提交事件指定处理函数
                <form onSubmit={ this.handleSubmit }>
                    {/* type 属性指定 input 元素的类型 */}
                    {/* name 属性指定每个 input 元素的唯一标识符 */}
                    {/* value 属性指向 state 数据,使得 state 成为唯一的数据源 */}
                    {/* onChange 属性为 value 改变指定处理函数 */}
                    您的姓名:<input type="text" name="userName" value={ this.state.name } onChange={ this.handleChange } /><br /><br />
                    您的手机:<input type="text" name="userPhone" value={ this.state.phone } onChange={ this.handleChange } /><br /><br />
                    <input type="submit" value="提交" />
                </form>
            )
        }
    }
    

    2、非受控组件

    除了通过受控组件让 React 组件管理表单数据,还能使用非受控组件让 DOM 节点处理表单数据

    编写非受控组件,我们无需为每个状态更新都写一个处理函数,只需使用 ref 从 DOM 节点中获取表单数据

    class InfoForm extends React.Component {
        constructor(props) {
            super(props)
            this.handleSubmit = this.handleSubmit.bind(this)
            // 使用 `React.createRef()` 创建 ref
            this.nameInput = React.createRef()
            this.phoneInput = React.createRef()
        }
    
        handleSubmit(event) {
            alert('您的名字是 ' + this.nameInput.current.value + ';' + '您的手机是 ' + this.phoneInput.current.value)
            event.preventDefault()
        }
    
        render() {
            return (
                // onSubmit 属性为提交事件指定处理函数
                <form onSubmit={ this.handleSubmit }>
                    {/* type 属性指定 input 元素的类型 */}
                    {/* ref 属性用于从 DOM 节点获取表单元素的值 */}
                    您的姓名:<input type="text" ref={ this.nameInput } /><br /><br />
                    您的手机:<input type="text" ref={ this.phoneInput } /><br /><br />
                    <input type="submit" value="提交" />
                </form>
            )
        }
    }
    

    【 阅读更多 React 系列文章,请看 React学习笔记

    版权声明:本博客属于个人维护博客,未经博主允许不得转载其中文章。
  • 相关阅读:
    行高 | line-height (Animations & Transitions)
    色域 | @media.color-gamut (Media Queries)
    自动换行 | word-wrap (Text)
    漫谈死锁
    《金融时间序列分析》第3版-蔡瑞胸
    《广告点击延时反馈建模》
    《Google软件测试之道》
    《持续集成:软件质量改进和风险降低之道》
    《DevOps实践:驭DevOps之力强化技术栈并优化IT运行》
    《架构真经:互联网技术架构的设计原则》
  • 原文地址:https://www.cnblogs.com/wsmrzx/p/11314579.html
Copyright © 2020-2023  润新知