一.React事件处理
-
React的事件是通过onXxx属性指定事件处理函数 ----为了更好的兼容性
- React使用的都是
自定义(合成)事件,而不是原生的事件 ----为了的高效 - React中的事件是通过
事件委托方式处理的
- React使用的都是
-
事件中必须返回的是函数
-
通过
event.target得到发生事件的DOM元素对象----不要过度使用 ref
发生事件的元素是需要操作的元素时,可以避免使用ref
//1.创建组件
class Demo extends React.Component {
/*
(1).通过onXxx属性指定事件处理函数(注意大小写)
a.React使用的是自定义(合成)事件,而不是使用的原生DOM事件 ———— 为了更好的兼容性
b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素) ———— 为了高效
(2).通过event.target得到发生事件的DOM元素对象
*/
myRef = React.createRef()
myRef2 = React.createRef()
//展示左侧输入框数据
showData = () => {
alert(this.myRef.current.value)
console.log(this.myRef)
}
//展示右侧输入框数据
showData2 = () => {
alert(this.myRef2.current.value)
}
render() {
return (
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示输入的数据</button>
<input onBlur={this.showData2} ref={this.myRef2} type="text"/>
</div>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Demo/>, document.getElementById('test'))
二、收集表单数据
1.理解包含表单的组件分类
- 受控组件
- 非受控组件
2.需求:定义一个包含的表单的组件,输入用户名后,密码登陆提示输入信息
2.1 非受控组件
页面中所有输入类DOM的值,都是现用现取的
//1.创建组件
class Login extends React.Component {
login = (event) =>{
event.preventDefault(); //阻止表单提交
alert(`你输入的的用户名:${this.name.value},密码是:${this.pwd.value}`);
}
render() {
return (
<form action="http://www.baidu.com" onSubmit={this.login}>
用户名:<input ref = {c => this.name =c } type = "text" name ="username"/>
密码<input ref = {c => this.pwd =c } type = "password" name ="password"/>
<button>登录</button>
</form>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Login/>, document.getElementById('test'))
2.2 受控组件
页面中输入类的DOM,随着输入的过程,将数据存储在状态state中,需要用的时候在从状态state中取(有点类似Vue中的双向数据绑定)
class Login extends React.Component{
state = {
name:"",
pwd:""
}
saveName = (event) =>{
this.setState({name:event.target.value});
}
savePwd = (event) => {
this.setState({pwd:event.target.value});
}
render() {
return (
<form action="http://www.baidu.com" onSubmit={this.login}>
用户名:<input onChange={this.saveName} type = "text" name ="username"/>
密码<input onChange={this.savePwd} type = "password" name ="password"/>
<button>登录</button>
</form>
)
}
}
ReactDOM.render(<Login />,document.getElementById("div"));
三.高阶函数与函数柯里化
3.1 高阶函数
高级函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高级而函数
- 若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
- 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
常见的高阶函数有: Promise、setTimeout、arr.map()等等
3.2 函数柯里化
函数柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
function sum1(a, b, c){
return a + b + c;
}
sum1(1, 2, 3)
// 柯里化后
function sum(a){
return(b)=>{
return (c)=>{
return a+b+c
}
}
}
sum(1)(2)(3)
3.3 利用 利用高阶函数与函数柯里化简写
class Login extends React.Component{
state = {
name:"",
pwd:""
}
login = (event) =>{
event.preventDefault(); //阻止表单提交
alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
}
//保存表单数据到状态中 (高阶函数+函数柯里化)
saveType = (type) =>{
return (event) => {
this.setState({[type]:event.target.value});
}
}
//因为事件中必须是一个函数,所以返回的也是一个函数,这样就符合规范了
render() {
return (
<form action="http://www.baidu.com" >
用户名:<input onChange = {this.saveType('name')} type = "text" name ="username"/>
{/*直接调用回调函数也是可以的:将数据传递过去就可以*/}
用户名:<input onChange = {(event)=>{this.saveType('name',event)}} type = "text" name ="username"/>
密码<input onChange = {this.saveType('pwd')} type = "password" name ="password"/>
<button>登录</button>
</form>
)
}
}
ReactDOM.render(<Login />,document.getElementById("test"));
3.4 不利用柯里化实现
class Login extends React.Component {
state = {
name: "",
pwd: ""
};
//保存表单数据到状态中
saveType = (type) => {
return (event) => {
this.setState({[type]: event.target.value});
}
}
//提交表单数据到状态中
login = (event) => {
event.preventDefault(); //阻止表单提交
const {name, pwd} = this.state
alert(`你输入的用户名是:${name},你输入的密码是${pwd}`)
}
render() {
return (
<form action="http://www.baidu.com">
用户名:<input onChange={this.saveType('name')} type="text" name="username"/>
{/*直接调用回调函数也是可以的:将数据传递过去就可以*/}
用户名:<input onChange={event => this.saveType('name', event)} type="text" name="username"/>
密码<input onChange={this.saveType('pwd')} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
ReactDOM.render(<Login/>, document.getElementById("test"));
四.组件的生命周期
4.1 理解
- 1.组件从创建到死亡它会经历一些特定的阶段。
- 2.React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
- 3.我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
4.2 引入案例
需求:定义组件实现以下功能:
- 1.让指定的文本做显示 / 隐藏的渐变动画
- 2.从完全可见,到彻底消失,耗时2S
- 3.点击“不活了”按钮从界面中卸载组件
//创建组件
//生命周期回调函数 <=> 生命周期钩子函数 <=> 生命周期函数 <=> 生命周期钩子
class Life extends React.Component {
//初始化状态,定义透明度为1
state = {opacity: 1}
death = () => {
//卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
//组件挂载完毕
componentDidMount() {
this.timer = setInterval(()=>{
//获取原状态
let {opacity} = this.state
//减少0.1
opacity -= 0.1
if (opacity <= 0) opacity = 1
//设置新的透明度
this.setState({opacity})
},200)
}
//组件将要卸载
componentWillUnmount() {
//清除定时器
clearInterval(this.timer)
}
//初始化渲染、状态更新之后
render() {
console.log('render')
return (
<div>
<h2 style={{opacity:this.state.opacity}}>React学不会怎么办?</h2>
<button onClick={this.death}>不活了</button>
</div>
)
}
}
//渲染页面
ReactDOM.render(<Life/>, document.getElementById("test"));
4.3 生命周期的三个阶段(旧)
4.3.1初始化阶段
由ReactDOM.render()触发---初次渲染
-
1.constructor() —— 类组件中的构造函数
-
2.componentWillMount() —— 组件将要挂载 【即将废弃】
-
3.render() —— 挂载组件
-
4.componentDidMount() —— 组件挂载完成 比较常用
- 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
class Count extends React.Component{
// 构造器
constructor(props){
alert('constructor')
console.log('Count---constructor');
super(props)
//初始化状态
this.state = {count:0}
}
add = () => {
const {count} = this.state
this.setState({count: count+1})
}
//组件将要挂载的钩子
componentWillMount(){
alert('componentWillMount')
console.log('Count---componentWillMount');
}
render(){
alert('render')
console.log('Count---render');
const {count} = this.state
return(
<div>
<h1>当前计数值:{count}</h1>
<button onClick={this.add}>点我+1</button>
</div>
)
}
//组件挂载完毕的钩子
componentDidMount(){
alert('componentDidMount')
console.log('Count---componentDidMount');
}
}
ReactDOM.render(<Count/>, document.getElementById('test'))
4.3.2更新阶段
【第一种情况】父组件重新render触发
- 1.
componentWillReceiveProps()—— 接收属性参数(非首次)【即将废弃】
然后调用下面的钩子函数
【第二种情况】由组件内部this.setSate()
- 1.
shouldComponentUpdate()—— 组件是否应该被更新(默认返回true)
然后调用下面的钩子函数
【第三种情况】强制更新 forceUpdate()
- 2.
componentWillUpdate()——组件将要更新 【即将废弃】 - 3.
render()—— 组件更新 - 4.
componentDidUpdate()—— 组件完成更新
4.3.3卸载组件
由ReactDOM.unmountComponentAtNode()触发
- 1.
componentWillUnmount()—— 组件即将卸载
4.4 生命周期的三个阶段(新)
4.4.1 初始化阶段
由ReactDOM.render()触发 —— 初次渲染
-
- constructor() —— 类组件中的构造函数
- 2.static getDerivedStateFromProps(props, state) 从props得到一个派生的状态【新增】
- 3.render() —— 挂载组件
- 4.componentDidMount() —— 组件挂载完成 比较==常用==
4.4.2 更新阶段
由组件内部this.setSate()或父组件重新render触发或强制更新forceUpdate()
- 1.
getDerivedStateFromProps()—— 从props得到一个派生的状态 【新增】 - 2.
shouldComponentUpdate()—— 组件是否应该被更新(默认返回true) - 3.
render()—— 挂载组件 - 4.
getSnapshotBeforeUpdate()—— 在更新之前获取快照【新增】 - 4
componentDidUpdate(prevProps, prevState, snapshotValue)—— 组件完成更新
4.4.3 卸载组件
由ReactDOM.unmountComponentAtNode()触发
- 1.componentWillUnmount() —— 组件即将卸载
4.4.3 重要的勾子
- 1.
render:初始化渲染或更新渲染调用 - 2.
componentDidMount:开启监听, 发送ajax请求 - 3.
componentWillUnmount:做一些收尾工作, 如: 清理定时器
4.4.4 即将废弃的勾子
- 1.componentWillMount
- 2.componentWillReceiveProps
- 3.componentWillUpdate
现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。
五.参考
React官网:react.docschina.org