小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
基础概念
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
- 通过 onXxx (camelCase)属性指定事件处理函数(注意大小写)。
- React 使用的是自定义(合成)事件,而不是使用原生 DOM 事件。—— 为了更好的兼容性
- React 中的事件是通过事件委托的方式处理的(委托给组件最外层的元素)—— 为了提高效率
- 事件处理函数默认入参是
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
高阶函数
如果一个函数符合下面两个规范中的任何一个,那该函数就是高阶函数:
- 若 A 函数,接收的参数是一个函数,那么 A 就可以称之为高阶函数。
- 若 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 中的事件处理属性需要接收到一个函数就可以,因此可以使用箭头函数实现。