1.React的Context
Context
提供了⼀个⽆需为每层组件⼿动添加 props
,就能在 组件树
间进⾏数据传递的⽅法。
Context的使用场景:
Context设计的⽬的是为了共享那些 全局 的数据,例如当前认证的⽤户、主题等。
🚀 下面是通过第①种渲染方式改变按钮主题的例子👇:
- 通过
React.createContext()
创建一个context
并赋值给变量ThemeContext
- 在
ThemeContext
组件中使用ThemeContext.Provider
进行包裹,并添加value属性
将值传出去 Context的ThemeContext.Provider
----→ToolBar
----→ThemeBtn
ThemeBtn
中如果是通过this.context使用value的值
的话,那么在组件中必须定义一个static自定义属性
去承载创建的ThemeContext
。- 组件中使用
this.context
渲染即可
🚀 此种渲染方式: 定制当前创建的 上下文对象
,为当前实例的 static静态属性
import React, {Component} from 'react';
import {Button} from "antd";
const ThemeContext = React.createContext();
class Context extends Component {
constructor(props) {
super(props);
this.state = {
store :{
type:"primary",
name:"按钮"
}
}
}
render() {
return (
<ThemeContext.Provider value = {this.state.store}>
<Toolbar> </Toolbar>
</ThemeContext.Provider>
);
}
}
export default Context;
function Toolbar(props){
return <ThemeBtn> </ThemeBtn>
}
//按钮Btn
class ThemeBtn extends Component {
constructor(props) {
super(props);
// 🚀 this有个叫context的属性,如果Provider中挂载了value值,那么this.context就会拿到这个值
console.log(this);
}
// 🚀 如果在组件中想要使用this.context必须先定义一个static静态属性值
static contextType = ThemeContext;
render() {
return (
<Button type={this.context}>初始化按钮</Button>
);
}
}
🚀 下面是通过第②种渲染方式改变按钮主题的例子👇:
- 前3步,步骤骤和
第①种
一样,第4步的时候是使用的ThemeContext.Consumer
对渲染出口的内容进行包裹。 ThemeContext.Consumer
内部使用通过一个箭头函数
去接收ThemeContext.Provider
提供的value
属性,返回一个jsx
, 然后在页面上完成渲染。
import React, {Component} from 'react';
import {Button} from "antd";
const ThemeContext = React.createContext();
class ThemeBtn extends Component {
constructor(props) {
super(props);
// 🚀 this有个叫context的属性,如果Provider中挂载了value值,那么this.context就会拿到这个值
console.log(this);
}
render() {
return (
<ThemeContext.Consumer>
{
(value)=>{
return (
<Button type={value.type}>初始化按钮</Button>
)
}
}
</ThemeContext.Consumer>
);
}
}
function Toolbar(props){
return <ThemeBtn> </ThemeBtn>
}
class Context extends Component {
constructor(props) {
super(props);
this.state = {
store :{
type:"primary",
name:"按钮"
}
}
}
render() {
return (
<ThemeContext.Provider value = {this.state.store}>
<Toolbar> </Toolbar>
</ThemeContext.Provider>
);
}
}
export default Context;
2.组件通信高组件装饰器写法:
将公用的部分抽出去,完成复用,从而完成对代码的瘦身减脂~!
下面是改造后的代码:
- 使用了高阶组件,抽离了公用的部分;
withProvider
为提供者;withConsumer
为消费者{...this.props}
就是保留原有的props
// 🌵index.js
import React,{Component} from "react";
const ThemeContext = React.createContext();
// 🚀 提供者
export const withProvider = Comp => {
return class extends Component{
constructor(props) {
super(props);
//共享的数据
this.state = {
store :{
type:"primary",
name:"按钮"
}
}
}
render() {
return(
<ThemeContext.Provider value={this.state.store}>
<Comp {...this.props}> </Comp>
</ThemeContext.Provider>
)
}
}
}
// 🚀 消费者
export const withConsumer = Comp => {
return class extends Component{
render() {
return (
<ThemeContext.Consumer>
{
(value)=>{
return (
//🚀 这里将value作为Comp的props传递下去
<Comp value = {value}> </Comp>
)
}
}
</ThemeContext.Consumer>
)
}
}
}
// 🌵Conetxt.js
import React, {Component} from 'react';
import {Button} from "antd";
import {withProvider,withConsumer} from "../HOC";
//🚀 消费者装饰器
@withConsumer
class ThemeBtn extends Component {
constructor(props) {
super(props);
}
render() {
// 🚀 这里通过this.props来接收
return <Button type={this.props.value.type}>装饰器初始化按钮</Button>
}
}
function Toolbar(props){
return <ThemeBtn> </ThemeBtn>
}
// 🚀 提供者装饰器
@withProvider
class Context extends Component {
render() {
return <Toolbar> </Toolbar>
}
}
export default Context;