React 基础小知识:事件处理

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

基础概念

React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:

  1. 通过 onXxx (camelCase)属性指定事件处理函数(注意大小写)。
  • React 使用的是自定义(合成)事件,而不是使用原生 DOM 事件。—— 为了更好的兼容性
  • React 中的事件是通过事件委托的方式处理的(委托给组件最外层的元素)—— 为了提高效率
  1. 事件处理函数默认入参是 event,可以通过 event.target 得到发生事件的 DOM 元素对象。
<button onClick={activateLasers}>Activate Lasers</button>
复制代码

非受控组件

非受控组件的表单数据将交由 DOM 节点来处理,可以使用 ref 来从 DOM 节点中获取表单数据。

class Login extends React.Component {
  handleSubmit = (event) => {
    event.preventDefault(); // 阻止表单提交
    const { username, password } = this
    alert(`用户名:${username.value},密码:${password.value}`)
  }
  render() {
    return(
      <form onSubmit={this.handleSubmit}>
        用户名:<input ref={c => this.username = c} type="text" name="username"/>
        密码:<input ref={c => this.password = c} type="password" name="password"/>
        <button>登录</button>
      </form>
    )
  }
}
ReactDOM.render(<Login />, document.getElementById("test"));
复制代码

受控组件

在一个受控组件中,表单数据是由 React 组件来管理的,应为每个状态更新都编写数据处理函数。

class Login extends React.Component {
  // 初始化状态
  state = {
    username: '',
    password: ''
  }
  // 保存用户名到 state
  saveUsername = (event) => {
    this.setState({username: event.target.value})
  }
  // 保存密码到 state
  savePassword = (event) => {
    this.setState({password: event.target.value})
  }
  // 表单提交的回调
  handleSubmit = (event) => {
    event.preventDefault(); // 阻止表单提交
    const { username, password } = this.state
    alert(`用户名:${username},密码:${password}`)
  }
  render() {
    return(
      <form onSubmit={this.handleSubmit}>
        用户名:<input onChange={this.saveUsername} type="text" name="username"/>
        密码:<input onChange={this.savePassword} type="password" name="password"/>
        <button>登录</button>
      </form>
    )
  }
}
ReactDOM.render(<Login />, document.getElementById("test"));
复制代码

类似 Vue 里面的 v-model

高阶函数

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

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

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

class Login extends React.Component {
  // 初始化状态
  state = {
    username: '',
    password: ''
  }
  
  // 保存表单数据到状态中
  saveFormData = (dataType) => {
    return (event) => {
      this.setState([dataType]: event.target.value)
    }
  }
  
  // 表单提交的回调
  handleSubmit = (event) => {
    event.preventDefault(); // 阻止表单提交
    const { username, password } = this.state
    alert(`用户名:${username},密码:${password}`)
  }
  
  render() {
    return(
      <form onSubmit={this.handleSubmit}>
        用户名:<input onChange={this.saveFormData('username')} type="text" name="username"/>
        密码:<input onChange={this.saveFormData('password')} type="password" name="password"/>
        <button>登录</button>
      </form>
    )
  }
}
ReactDOM.render(<Login />, document.getElementById("test"));
复制代码

React 中的事件处理属性需要接收一个函数,因此当我们调用 this.saveFormData('username') 的时候需要返回一个内部函数,且该内部函数可以接受 event 对象。

函数柯里化

通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码方式。

function sum(a) {
  return (b) => {
    return (c) => {
      return a + b + c
    }
  }
}
const result = sum(1)(2)(3)
console.log(result)
复制代码

上面案例中 saveFormData 就应用到了函数柯里化。

非函数柯里化

class Login extends React.Component {
  // 初始化状态
  state = {
    username: '',
    password: ''
  }
  
  // 保存表单数据到状态中
  saveFormData = (dataType, event) => {
    this.setState([dataType]: event.target.value)
  }
  
  // 表单提交的回调
  handleSubmit = (event) => {
    event.preventDefault(); // 阻止表单提交
    const { username, password } = this.state
    alert(`用户名:${username},密码:${password}`)
  }
  
  render() {
    return(
      <form onSubmit={this.handleSubmit}>
        用户名:<input onChange={(event) => {this.saveFormData('username', event)}} type="text" name="username"/>
        密码:<input onChange={(event) => {this.saveFormData('username', event)}} type="password" name="password"/>
        <button>登录</button>
      </form>
    )
  }
}
ReactDOM.render(<Login />, document.getElementById("test"));
复制代码

只要能保证 React 中的事件处理属性需要接收到一个函数就可以,因此可以使用箭头函数实现。

猜你喜欢

转载自juejin.im/post/7018770091395252232