React系列文章导航
案例如下:
jsx语法中,render()
里面最外层的标签,同级的不能有两个,如下
可以使用Fragment
包起来,来解决上述问题:
Context,一种组件通信方式,常用于祖组件
和子类组件
之间的通信。
案例如下:
import React, { Component } from 'react'
import './index.css'
const MyContext = React.createContext()
const { Provider, Consumer } = MyContext
export default class A extends Component {
state = { username: 'tom', age: 18 }
render() {
const { username, age } = this.state
return (
<div className="parent">
<h3>我是A组件</h3>
<h4>我的用户名是:{username}</h4>
<Provider value={{ username, age }}>
<B />
</Provider>
</div>
)
}
}
class B extends Component {
render() {
return (
<div className="child">
<h3>我是B组件</h3>
<C />
</div>
)
}
}
// 类式组件的用法
// class C extends Component {
// // 声明接收context
// static contextType = MyContext
// render() {
// const { username, age } = this.context
// return (
//
// 我是C组件
// 我从A组件中接收到的用户名是:{username}
// 我从A组件中接收到的年龄是:{age}
//
// )
// }
// }
// 函数式组件的用法,必须使用到Consumer标签
function C() {
return (
<div className="grand">
<h3>我是C组件</h3>
<h4>我从A组件中接收到的用户名是:
<Consumer>
{value => `${value.username},年龄是${value.age}`}
</Consumer>
</h4>
</div>
)
}
index.css
文件:
.parent{
width: 500px;
background-color: orange;
padding: 8px;
}
.child{
width: 100%;
background-color: skyblue;
padding: 8px;
}
.grand{
width: 400px;
background-color: gray;
padding: 10px;
}
从代码结构来看,A是父类,B是A的子类,C是B的子类,哪怕B没有传递对应的属性,C依旧可以获取到A类的值。
创建Context
容器对象:const xxx= React.createContext()
渲染子组件时,外面包裹xxx.Provider
标签,通过value
属性给后代组件传递数据:
<xxxContext.Provider value={数据}>
<子组件/>
</xxxContext.Provider>
xxx.Provider
包裹的一个子组件,那么该子组件以及其后代都能够直接获取到对应的数据,只需要声明接收context
即可。//第一种方式:仅适用类组件
// 声明接收context,contextType命名是固定的
static contextType = xxxContext
// 读取context中的value数据
this.context
//第二种方式: 函数组件与类组件都可以
<xxxContext.Consumer>
{
value => ( // value就是context中的value数据
要显示的内容
)
}
</xxxContext.Consumer>
这一小节主要来说说组件的优化,其实Component
有2个问题
只要执行setState()
,即使不改变状态数据,。组件也会重新调用render()
函数,效率低。
只当前组件重新render()
,就会自动重新渲染子组件, 纵使子组件没有用到父组件的任何数据,效率低
效率高的情况是怎么样的呢?就是:只有当组件的state
或props
数据发生改变时才重新调用render()
,即不会收父组件以及setState()
方法的影响。
案例1:
import React, { Component } from 'react'
import './index.css'
export default class Parent extends Component {
state = { carName: '奔驰' }
changeCar = () => {
this.setState({ carName: '宝马' })
}
render() {
console.log('Parent----render')
const {carName} = this.state
return (
<div className="parent">
<h3>我是Parent组件</h3>
<span>车名:{carName}</span><br/>
<button onClick={this.changeCar}>换车</button>
<Child carName="奥拓"/>
</div>
)
}
}
class Child extends Component {
render() {
console.log('Child----render')
return (
<div className="child">
<h3>我是Child组件</h3>
<span>我接收到的车是:{this.props.carName}</span>
</div>
)
}
}
点击换车
按钮后可以发现:子组件也重新调用了render()
进行了渲染。
那么如何对上述问题进行修改呢?
重写shouldComponentUpdate()
方法:
import React, { Component } from 'react'
import './index.css'
export default class Parent extends Component {
state = { carName: '奔驰' }
changeCar = () => {
this.setState({ carName: '宝马' })
}
render() {
console.log('Parent----render')
const { carName } = this.state
return (
<div className="parent">
<h3>我是Parent组件</h3>
<span>车名:{carName}</span><br />
<button onClick={this.changeCar}>换车</button>
<Child carName="奥拓" />
</div>
)
}
}
class Child extends Component {
shouldComponentUpdate(nextProps, nextState) {
return !this.props.carName === nextProps.carName
}
render() {
console.log('Child----render')
return (
<div className="child">
<h3>我是Child组件</h3>
<span>我接收到的车是:{this.props.carName}</span>
</div>
)
}
}
引用PureComponent
import React, { PureComponent } from 'react'
import './index.css'
export default class Parent extends PureComponent {
state = { carName: '奔驰' }
changeCar = () => {
this.setState({ carName: '宝马' })
}
render() {
console.log('Parent----render')
const { carName } = this.state
return (
<div className="parent">
<h3>我是Parent组件</h3>
<span>车名:{carName}</span><br />
<button onClick={this.changeCar}>换车</button>
<Child carName="奥拓" />
</div>
)
}
}
class Child extends PureComponent {
render() {
console.log('Child----render')
return (
<div className="child">
<h3>我是Child组件</h3>
<span>我接收到的车是:{this.props.carName}</span>
</div>
)
}
}
原理如下:
PureComponent
重写了shouldComponentUpdate()
,,只有state
或props
数据有变化才返回true
注意:
state
和props
数据的浅比较,如果只是数据对象内部数据变了,返回false
。state
数据,,而是要产生新数据。