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

简介: 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>
        )
    }
}



目录
相关文章
|
1月前
|
移动开发 前端开发 JavaScript
React 表单与事件
10月更文挑战第10天
38 1
|
1月前
|
前端开发 JavaScript 容器
React 元素渲染
10月更文挑战第7天
25 1
|
1月前
|
前端开发 JavaScript 数据安全/隐私保护
深入探索研究React表单
【10月更文挑战第6天】
89 57
|
17天前
|
前端开发 JavaScript
React 表单处理技巧
【10月更文挑战第24天】本文从初学者角度出发,详细介绍了 React 中表单处理的基本概念、常见问题及解决方案。涵盖受控组件与非受控组件的区别、状态更新、表单验证、多字段管理及高级技巧,通过代码示例帮助读者更好地理解和应用。
46 7
|
17天前
|
前端开发 JavaScript 开发者
React 事件处理机制详解
【10月更文挑战第23天】本文介绍了 React 的事件处理机制,包括事件绑定、事件对象、常见问题及解决方案。通过基础概念和代码示例,详细讲解了如何处理 `this` 绑定、性能优化、阻止默认行为和事件委托等问题,帮助开发者编写高效、可维护的 React 应用程序。
61 4
|
1月前
|
XML 前端开发 JavaScript
react学习笔记一:入门级小白到脚手架(create-react-app)开发项目
这篇文章是React的学习笔记,覆盖了从React的基础用法到高级特性,包括组件化、状态管理、生命周期、虚拟DOM等主题,适合React初学者参考。
92 0
react学习笔记一:入门级小白到脚手架(create-react-app)开发项目
|
1月前
|
前端开发 JavaScript IDE
React 事件处理
10月更文挑战第8天
19 1
|
1月前
|
前端开发 JavaScript
一文详解React事件中this指向,面试必备
一文详解React事件中this指向,面试必备
44 0
|
2月前
|
前端开发 JavaScript
react学习(19)事件处理
react学习(19)事件处理
|
1月前
|
移动开发 JSON 数据可视化
精选八款包括可视化CMS,jquery可视化表单,vue可视化拖拉,react可视化源码
精选八款包括可视化CMS,jquery可视化表单,vue可视化拖拉,react可视化源码
48 0