JavaScript中React面向组件编程实例代码分析
一、受控组件与非受控组件
表单的组件分类:
受控组件
非受控组件
多数情况下,推荐使用受控组件实现表单。在受控组件中,表单数据由组件控制。
另外一种是非受控组件,这种方式下表单组件由DOM自身控制。
1. 受控组件
受控组件通过
props获取其当前值,并通过回调函数(比如onChange)通知变化表单状态发生变化时,都会通知
React,将状态交给React进行处理,比如可以使用useState存储受控组件中,组件渲染出的状态与它的
value或checked属性相对应受控组件会更新
state的流程
class Login extends React.Component {
// 初始化状态
state = {
username:'', // 用户名
password:'', // 密码
}
// 保存用户名到状态中
saveUsername=(event)=>{
this.setState({username:event.target.value})
}
// 保存密码到状态中
savePassword=(event)=>{
this.setState({password:event.target.value})
}
// 表单提交的回调
handleSubmit=(event)=>{
event.preventDefault(); // 阻止默认事件
let {username,password} = this.state
alert(`你输入的用户名是${username},密码是${password}`)
}
render(){
return(
)
}
}2. 非受控组件
非受控组件将数据存储在 DOM 中,而不是组件内,这比较类似于传统的 HTML 表单元素。
非受控组件的值不受组件自身的
state和props控制非受控组件使用
ref从DOM中获取元素数据
class Login extends React.Component {
handleSubmit=(event)=>{
// console.log(e>=event)
event.preventDefault(); // 阻止默认事件
let {username,password} = this
alert(`你输入的用户名是${username.value},密码是${password.value}`)
}
render(){
return(
)
}
}3. 效果展示

4. 总结:
React中的组件分为受控组件和非受控组件受控组件的两个要点:
组件的
value属性与React中的状态绑定组件内声明了
onChange事件处理value的变化
非受控组件更像是传统的 HTML 表单元素,数据存储在 DOM 中,而不是组件内部,获取数据的方式是通过 ref 引用
一些建议:
尽可能使用受控组件
受控组件是将状态交由
React处理,可以是任何元素,不局限于表单元素对于有大量表单元素的页面,使用受控组件会使程序变得繁琐难控,此时使用非受控组件更为明智
在受控组件中,数据流是单向的(
state是变化来源),因此在改变state时都应该使用setState,而不要强制赋值Refs不能用于函数式组件,因为函数式组件没有实例在函数式组件内部,是可以使用
Refs的
二、组件的生命周期
所谓的React生命周期,就是指组件从被创建出来,到被使用,最后被销毁的这么一个过程;
而在这个过程中,React提供了我们会自动执行的不同的钩子函数,我们称之为生命周期函数;
组件的生命周期大致分为三个阶段:组件挂载阶段,组件更新阶段,组件销毁卸载阶段
react在版本16.3前后存在两套生命周期,16.3之前为旧版,之后则是新版,虽有新旧之分,但主体上大同小异。
1. 对生命周期的理解
组件从创建到死亡它会经历一些特定的阶段。
React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
2. 生命周期的三个阶段(旧)

初始化阶段: 由ReactDOM.render()触发—初次渲染
constructor()
componentWillMount()
render()
componentDidMount()
更新阶段: 由组件内部this.setSate()或父组件重新render触发
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
卸载组件: 由ReactDOM.unmountComponentAtNode()触发
componentWillUnmount()
生命周期旧
3. 生命周期的三个阶段(新)

初始化阶段: 由ReactDOM.render()触发—初次渲染
constructor()
getDerivedStateFromProps
render()
componentDidMount()
更新阶段: 由组件内部this.setSate()或父组件重新render触发
getDerivedStateFromProps
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate
componentDidUpdate()
卸载组件: 由ReactDOM.unmountComponentAtNode()触发
componentWillUnmount()
生命周期新
4. 新旧生命周期的区别
新生命周期中去掉了三个
will钩子,分别为componentWillMount、componentWillReceiveProps、componentWillUpdate;新生命周期中新增了两个钩子,分别为
getDerivedStateFromProps(从props中得到衍生的state)和getSnapshotBeforeUpdate。
5. 重要的勾子
render:初始化渲染或更新渲染调用componentDidMount:开启监听, 发送ajax请求componentWillUnmount:做一些收尾工作, 如: 清理定时器
6. 即将废弃的勾子
componentWillMountcomponentWillReceivePropscomponentWillUpdate
警告:
现在使用会出现警告,下一个大版本需要加上
UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。
三、高阶函数和函数柯里化的理解
1. 高阶函数
如果一个函数符合下面2个规范中的任何一个,那么它就属于一个高阶函数
若A函数,接收的参数是一个函数,那么A就可以称为高阶函数
若A函数,它的返回值依然是一个函数,那么A就可以称为高阶函数
常见的高阶函数:Promise,setTimeout,arr.map(数组方法)
2. 函数的柯里化
通过函数继续调用,返回值为函数的方式,实现多次接受参数,最后统一处理的函数编码形式
function sum(a){
return (b)=>{
return (c)=>{
return a + b + c
}
}
}
const result = sum(1)(2)(3)
console.log(result);3. 使用函数柯里化代码示例
class Login extends React.Component {
// 初始化状态
state = {
username:'', // 用户名
password:'', // 密码
}
// 保存表单数据到状态中
saveFormDate=(dataType,event)=>{ // 标识当前标签
this.setState({[dataType]:event.target.value})
}
// 表单提交的回调
handleSubmit=(event)=>{
event.preventDefault(); // 阻止默认事件
let {username,password} = this.state
alert(`你输入的用户名是${username},密码是${password}`)
}
render(){
return(
)
}
}4. 不用函数柯里化代码示例
class Login extends React.Component {
// 初始化状态
state = {
username:'', // 用户名
password:'', // 密码
}
// 保存表单数据到状态中
saveFormDate=(dataType)=>{ // 标识当前标签
return (event)=>{ // 这里的回调谁执行? input标签的 onChange事件
this.setState({[dataType]:event.target.value})
}
}
// 表单提交的回调
handleSubmit=(event)=>{
event.preventDefault(); // 阻止默认事件
let {username,password} = this.state
alert(`你输入的用户名是${username},密码是${password}`)
}
render(){
return(
)
}
}