事件处理、受控组件和非受控组件、高阶函数和函数柯里化

事件处理

  1. 通过onXxx属性指定事件处理函数(注意大小写)
  • React使用的是自定义(合成)事件, 而不是使用的原生DOM事件。
    优点:onClick是比onclick(原生事件)兼容性更好
  • React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
    优点:更高效
  • 在jsx语法中的事件属性接受的是函数,所以函数名后面无需写 () ;如果必须要传递参数,需要该函数的返回值也是一个函数。
    eg:
import React, {
    
     Component } from 'react'
import PropyTypes from 'prop-types'
import './index.css'

export default class index extends Component {
    
    
  // 对Props进行类型的限制
  static propsTypes = {
    
    
    updateTodo: PropyTypes.func.isRequired,
    id: PropyTypes.string.isRequired,
    name: PropyTypes.string.isRequired,
    done: PropyTypes.bool.isRequired
  }
  state = {
    
    mouse:false}
  handleMouse = (flag)=>{
    
    
    // 在标签中函数使用了括号
    return () => {
    
    
      this.setState({
    
    mouse:flag})
    }
  }
  handleChange = (id) => {
    
    
    return (event) => {
    
    
      // 注意是checked不是value
      const checked =  event.target.checked;
      this.props.updateTodo(id, checked)
    }
  }
  handleDelete = (id)=>{
    
    
    if(window.confirm("确定删除吗?")){
    
    
      this.props.deleteTodo(id)
    }
  }
  render() {
    
    
    const {
    
    id, name, done} = this.props
    const {
    
    mouse} = this.state;
    return (
        <li style={
    
    {
    
    backgroundColor: mouse? '#ddd':'white'}} onMouseEnter = {
    
    this.handleMouse(true)} onMouseLeave = {
    
    this.handleMouse(false)}>
            <label>
              {
    
    /* 使用checked,必须要结合onChange事件才能进行修改
               而defaultChecked,初次页面展示时是否勾选,当数据再发生改变的时候就不好用了*/}
                <input type="checkbox" checked = {
    
    done} onChange = {
    
    this.handleChange(id)}/>
                <span>{
    
    name}</span>
            </label>
            <button onClick={
    
    () => {
    
    this.handleDelete(id)}} className="btn btn-danger" style={
    
    {
    
    display:mouse?"block":"none"}}>删除</button>
        </li>
    )
  }
}
  1. 可以使用ref来存储当前节点,再结合事件的回调函数进行节点数据的处理。
  2. 也 可以通过event.target得到发生事件的DOM元素对象
    当发生事件的元素正好是要操作的元素的时候我们尽量使用evet.target获取数据,不要过度地使ref
    eg:
<!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>字符串ref</title>
</head>
<body>
    <!-- 容器 -->
    <div id="test"></div>

    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <script type="text/babel">
        //  <!-- 1.创建类式组件 -->
        class Demo extends React.Component{
      
      
            // React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专川用”的(即一个createRef只能存储一个dom元素)
            myRef = React.createRef()

            showDataClick = ()=>{
      
      
                alert(this.myRef.current.value)
            }
            showDataBlur = (event)=>{
      
      
                // event发生事件的事件源
                alert(event.target.value)
            }
            render(){
      
      
                return (
                    <div>
                        {
      
      /*ref方式*/}
                        <input ref={
      
      this.myRef} type="text" id="input1" placeholder="点击按钮提示数据"/>
                        <button onClick={
      
      this.showDataClick}>点我提示左侧数据</button>&nbsp;
                        {
      
      /*event.Target方式*/}
                        <input onBlur={
      
      this.showDataBlur} type="text" placeholder="失去焦点提示数据"/>
                    </div>
                )
            }
        }

        // <!--2.渲染虚拟DOM到页面 -->
        ReactDOM.render(<Demo/>,document.getElementById('test'))  
    </script>
</body>
</html> 

受控组件和非受控组件

  • 非受控组件:表单中所有输入类的DOM 现用现取的就是非受控组件
    现用现取即需要用到该数据的时候再获取
  • 受控组件:将数据先存放在state中,再显示到页面上。——有点类似于vue的双向数据绑定,只不过在react中需要自己手动实现。

需求:
在这里插入图片描述
有用户名和密码,当点击登陆的时候会弹窗提示用户名和密码。

受控组件实现:——数据存储在state

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

    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <script type="text/babel">
        //  <!-- 1.创建类式组件 -->
        class Login extends React.Component{
      
      
            // 初始化状态
            state={
      
      
                username:'',
                password:''
            }
            handlesubmit = (event)=>{
      
      
                event.preventDefault()//阻止默认事件,表单的提交
                const {
      
      username,password} = this.state
                alert(`用户名:${ 
        username},密码:${ 
        password}`)
            }
            // 保存用户名到username
            saveUsername = (event)=>{
      
      
                this.setState({
      
      username:event.target.value})
            }
            // 保存
            savePassword = (event)=>{
      
      
                this.setState({
      
      password:event.target.value})
            }
            render(){
      
      
                return(
                    <form action="http://www.baidu.com" onSubmit={
      
      this.handlesubmit} >
                        {
      
      /*onchange也是一个原生的事件,当内容发生改变就会调用该函数*/}
                        用户名:<input onChange={
      
      this.saveUsername} type="text" name="username"/><br/>
                        密码:<input onChange={
      
      this.savePassword} type="password" name="password"/><br/> 
                        <button>登录</button>
                    </form>
                )
            }
        }
        // <!--2.渲染虚拟DOM到页面 -->
        ReactDOM.render(<Login/>,document.getElementById('test'))
        
    </script>
    <!-- 受控组件:数据先存放在state中,再显示到页面上 -->

</body>
</html> 

非受控组件实现:—— 数据存储在组件实例上

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

    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <script type="text/babel">
        //  <!-- 1.创建类式组件 -->
        class Login extends React.Component{
      
      
            handlesubmit = (event)=>{
      
      
                event.preventDefault()//阻止默认事件,表单的提交
                const {
      
      username,password} = this
                alert(`用户名:${ 
        username.value},密码:${ 
        password.value}`)
            }
            render(){
      
      
                return(
                    // form表单默认是get请求,query参数
                    // form会默认提交并刷新页面,即使没有配路径
                    <form action="http://www.baidu.com" onSubmit={
      
      this.handlesubmit} >
                        用户名:<input ref={
      
      c=>this.username=c} type="text" name="username"/><br/>
                        密码:<input ref={
      
      c=>this.password=c} type="password" name="password"/><br/> 
                        <button>登录</button>
                    </form>
                )
            }
        }
        // <!--2.渲染虚拟DOM到页面 -->
        ReactDOM.render(<Login/>,document.getElementById('test'))
        
    </script>
    <!-- 非受控组件:表单中所有输入类的DOM 现用现取的就是非受控组件 -->

</body>
</html> 

高阶函数和函数柯里化

高阶函数

上述代码有点冗余,函数结构类似只是值不一样,可以提取为一个函数。

<!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>字符串ref</title>
</head>
<body>
    <!-- 容器 -->
    <div id="test"></div>

    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <script type="text/babel">
        //  <!-- 1.创建类式组件 -->
        class Login extends React.Component{
      
      
            // 初始化状态
            state={
      
      
                username:'',
                password:''
            }
            handlesubmit = (event)=>{
      
      
                event.preventDefault()//阻止默认事件,表单的提交
                const {
      
      username,password} = this
                alert(`用户名:${ 
        this.state.username},密码:${ 
        this.state.password}`)
            }
            saveFormData=(dataType)=>{
      
      
                // onChange的值需要是一个回调函数,onChange回调函数的参数是event
                return (event)=>{
      
      
                    // dataType是一个变量,作为键值时需要使用[],确保读取变量中的值
                     this.setState({
      
      [dataType]: event.target.value})
                }
            }
            render(){
      
      
                return(
                    <form action="http://www.baidu.com" onSubmit={
      
      this.handlesubmit} >
                        用户名:<input onChange={
      
      this.saveFormData('username')} type="text" name="username"/><br/>
                        密码:<input onChange={
      
      this.saveFormData('password')} type="password" name="password"/><br/> 
                        <button>登录</button>
                    </form>
                )
            }
        }
        // <!--2.渲染虚拟DOM到页面 -->
        ReactDOM.render(<Login/>,document.getElementById('test'))
    </script>
</body>
</html> 

上述代码中的saveFormData就是一个高阶函数。

高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。

  • 若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
  • 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。

常见的高阶函数有:Promise、setTimeout、 arr.map() 等

函数柯里化

函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。
上述的代码就应用了柯里化:

    saveFormData=(dataType)=>{
    
    
        return (event)=>{
    
    
             this.setState({
    
    [dataType]: event.target.value})
        }
    }

猜你喜欢

转载自blog.csdn.net/mantou_riji/article/details/127270512