一些React扩展知识——Fragment、Context和组件优化
一些React扩展知识
1. Fragment
有些时候render的函数里面返回的html模板必须在外面包一个div,但是这个Fragment就可以解决这个问题,可以包一个Fragement或者空标签
代码使用
//Fragement标签,Fragement允许写key值
<Fragment><Fragment/>
//空标签,空标签不允许写任何属性
<></>
作用
可以不用必须有一个真实的DOM根标签
2. Contex
理解
一种组件间的通信方式,常用于【祖组件】与【后代组件】间通信
使用
//创建Context容器对象,这个容器必须放在父子孙都能访问到的位置
const xxxContext=React.createContext()
//渲染子组件时,外面包裹xxxContext.Provider,通过value属性给后代组件传递数据;
<xxxContext.Provider value={数据}>
子组件
</xxxContext.Provider>
//后代组件读取数据
//第一种方式:仅适用于类组件
static contextType=xxxContext //声明接收context
this.context //读取context中value的数据
//第二种方式:函数组件和类组件都可以
<xxxContext.Consumer>
{
value=>{//value就是context中的value数据
要显示的内容}
}
</xxxContext.Consumer>
注意
在应用开发中一般不用context,一般都用它的封装react组件
3. 组件优化
import React,{Component} from 'react'
export default class Parent extends Component{
state={carName:"奔驰C36"}
changeCar=()=>{
this.setState({carName:'迈巴赫'})
}
render(){
const {carName}=this.state
return (
<div>
<h3>我是parent组件</h3>
<span>我的车名字是:{this.state.carName}</span><br/>
<button onClick={this.changeCar}>点我换车</button>
<Child carName={carName}/>
</div>
)
}
}
class Child extends Component{
render(){
return (
<div>
<h3>我是child组件</h3>
<span>我接到的车是:{this.state.carName}</span>
</div>
)
}
}
在上述例子中,如果父组件的数据更新了,父组件的render会调用一次,子组件的render也会调用一次
哪怕父组件不传数据给子组件,子组件的render也会调用一次,下面进行总结:
Component的两个问题
- 只要执行setState(),即便不改变状态数据,组件也会重新render()
- 只要当前组件重新render(),就会自动重新render子组件,纵使子组件没有用到父组件的任何数据==>效率低
效率高的做法
只有当组件的state或props数据发生改变的时候才重新render()
原因
Component中的shouldComponentUpdate()总是返回true
解决
//办法1:
重写shouldComponentUpdate()方法
比较新旧state和props数据,如果有变化才返回true,如果没有就返回false
//办法2:
使用PureComponent
PureComponent重写了shouldComponentUpdate(),只有state或props数据有变化才返回true
注意:
只是进行state和props数据的浅比较,如果只是数组对象内部数据变了,返回false
不要直接修改state中数据,而是要产生新的数据
项目中一般不用PureComponent来优化
下面就上面的例子,分别列举解决办法,首先是自定义shouldComponentUpdate:
import React,{Component} from 'react'
export default class Parent extends Component{
state={carName:"奔驰C36"}
changeCar=()=>{
this.setState({carName:'迈巴赫'})
}
shouldComponentUpdate(nextProps,nextState){
//nextProps,nextState:接下来要变化的目标props,目标state
//this.props,this.state:目前的props和state
if(this.state.carName===nextState.carName) return false
else return true
}
render(){
const {carName}=this.state
return (
<div>
<h3>我是parent组件</h3>
<span>我的车名字是:{this.state.carName}</span><br/>
<button onClick={this.changeCar}>点我换车</button>
<Child carName={carName}/>
</div>
)
}
}
class Child extends Component{
shouldComponentUpdate(nextProps,nextState){
//nextProps,nextState:接下来要变化的目标props,目标state
//this.props,this.state:目前的props和state
if(this.props.carName===nextProps.carName) return false
else return true}
render(){
return (
<div>
<h3>我是child组件</h3>
<span>我接到的车是:{this.state.carName}</span>
</div>
)
}
}
第二种方法是使用PureComponent:
import React,{PureComponent} from 'react'
export default class Parent extends PureComponent{
state={carName:"奔驰C36"}
changeCar=()=>{
this.setState({carName:'迈巴赫'})
}
render(){
const {carName}=this.state
return (
<div>
<h3>我是parent组件</h3>
<span>我的车名字是:{this.state.carName}</span><br/>
<button onClick={this.changeCar}>点我换车</button>
<Child carName={carName}/>
</div>
)
}
}
class Child extends PureComponent{
render(){
return (
<div>
<h3>我是child组件</h3>
<span>我接到的车是:{this.state.carName}</span>
</div>
)
}
}