在React中提供两种形式,一种是 类组件 ,另一种是 函数式组件,而在类组件组件中需要使用Component继承。
Component
继承一些初始化数据props,context,refs,以及更新组件的方法updater
PureComponent
通过 prop 和 state 的浅比较来实现shouldComponentUpdate,某些情况下可以用 PureComponent 提升性能,减少界面渲染次数,达到优化效果。
shouldComponentUpdate
此方法在继承PureComponent类时候默认存在,不需要单独定义,只是与需要主要他的浅层比较会忽略子属性变化,必要时用结构赋值使数据更新。
shouldComponentUpdate(nextProps, nextState) {
//返回 true 则表示通过比较新返回的元素和之前渲染的元素,两者不相等,此时更新DOM
return true;
}
memo
memo是一个高阶组件,结合了pureComponent纯组件和 componentShouldUpdate功能,会对传入的props进行一次对比,然后根据第二个函数返回值来进一步判断哪些props需要更新。函数式组件和类组件都可以使用。
作用:
当组件中包含一些不随着组件状态变化的子组件时(setState会导致界面重新渲染,包括子组件),可用进行优化。
memo(Child, (pre, next) => {
return true
//memo:返回 true 组件不渲染 , 返回 false 组件重新渲染,且只针对props
//shouldComponentUpdate: 返回 true 组件渲染 , 返回 false 组件不渲染。
})
react中event事件
- react中event事件是syntheticEvent 是一个合成事件
- event.nativeEvent是原生事件对象
- 所有事件都挂载在document上
- 和dom事件不一样,和vue事件也不一样
受控组件
例如<input><select><textearea>
等元素都要绑定一个change事件,当表单的状态发生变化,就会触发onChange事件,更新组件的state。这种组件在React中被称为受控组件
受控组件更新state的流程:
可以通过初始state中设置表单的默认值
每当表单的值发生变化时,调用onChange事件处理器
事件处理器通过事件对象e拿到改变后的状态,并更新组件的state
一旦通过setState方法更新state,就会触发视图的重新渲染,完成表单组件的更新
非受控组件
- 必须要操作dom时候,setState实现不了的,使用非控
- 使用defaultValue而不是value,使用ref
calss App extends React.Componet {
constructor(props){
super(props)
this.nameInputRef = React.createRef() //创建ref
}
render(){
return <div>
<input defaultValue={this.state.name} ref={this.nameInputRef}/>
<button onClick={this.alertName}>btn</button>
</div>
}
alertName=()=>{
//通过ref拿到dom节点
const ele = this.nameInputRef.current
alert(ele.value)
}
}
如果一个表单组件只是初始值用了state后面变化和state没有关系,通过ref去拿值,就可以称为非受控组件.
在非受控组件中,我们可以使用一个ref来从DOM获得表单值。而不是为每个状态更新编写一个事件处理程序
setState
- 不可变值(函数式编程,纯函数)
- 可能是异步更新
- 可能会被合并
1. 不可变值
不能对this.state原值进行修改。
数组修改
可用 concat,结构赋值,slice,filter,或者拷贝一份副本在进行修改
数组对象
可用 object.assign(),结构赋值
2. 可能异步
异步
一般正常使用setState是异步的
this.setState({
count: this.state.count +1
},()=>{
// 这里能拿到同步值,参考vue的$nextTick
})
同步
- 在setTimeOut中是同步的
- 在自定义事件中是同步的
3. 可能合并
合并
传入对象,操作会被合并,最终只执行一次+1
this.setState({
count: this.state.count +1
})
this.setState({
count: this.state.count +1
})
不合并
传入函数,不会被合并,最终会执行+2
this.setState((prev,props)=>{
return{
count: prev.count +1
}
})
this.setState((prev,props)=>{
return{
count: prev.count +1
}
})
常用生命周期
外加 shouldComponentUpdate
函数组件
- 纯函数 输入 props 输出jsx
- 没有实例 没有生命周期 没有state
- 无法拓展其他方法
Portals
让组件渲染到父组件之外,比如制作modal
return ReactDOM.creatPottal(
<div className="modal">{this.props.children}</div>,
document.body
)
Context
最外层定义数据,内层去消费
//外层
const myContext = React.createContext('数据')
render(){
return <myContext.Provider value={this.state.data}>
<Bar/>
</myContext.Provider>
}
//里层 class组件
class Bar extends React.Componet {
render() {
// react会往上找最近的 Provider
// 也可以写成
//1. static contextType = myContext
const data= this.context
return <div>{data}</div>
}
}
// 2. 写在外面也可以
Bar.contextType = myContext
//里层 函数组件
function Bar(props){
return <myContext.Consumer>
{value => <p>{value}</p>
</myContext.Consumer>
}
异步组件
- import()
- React.lazy
- React.Suspense
const Demo = React.lazy(()=> import('./Dmeo'))
<React.Suspense fallback={<p>loading...</p>}>
<Demo/>
</React.Suspense>