Context
作用:给整个组件树共享全局的数据
最适合的场景:杂乱无章的组件都需要同一些数据
如果单纯为了不层层传递属性的话, Context
是不合适的,因为 Context
会弱化及污染组件的纯度,导致组件复用性降低
Context API
Context.Provider
数据提供者
通过React.createContext
创建的一个上下文对象里的组件,Provider
组件中可以插入其他组件,来订阅这个Context
;
通过Provider
的value
将数据传递给Consumer
组件;Context.Consumer
数据消费者
订阅Context
的变更;
组件会找离自己最近的Provider
,获取其value
;
value
变化,插入Provider
的组件都会重新渲染;
没有匹配到Provider
,使用默认值;其他情况均不使用默认参数;
新旧 value
值对比,用的是和 Object.is
相同的算法
案例1:更改主题
/* Header.css */
.header{
position: fixed;
top: 0;
left: 0;
right: 0;
height: 50px;
line-height: 50px;
background-color: black;
color: #fff;
}
.header.red{
background-color: red;
}
.header.pink{
background-color: pink;
}
// context.js
const ThemeContext = React.createContext('black')
export {
ThemeContext
}
// Header.jsx
import "./Header.css";
import { ThemeContext } from "./context";
export default class Header extends React.Component {
render() {
return (
{(theme) => (
{this.props.children}
)}
);
}
}
// index.jsx
import Header from "./context_comps/Header";
import { ThemeContext } from "./context_comps/context";
class App extends React.Component {
state = {
theme: "black",
};
render() {
return (
This is a title
);
}
}
案例2:使用组合方式解决数据传递问题
class App extends React.Component {
state = {
headerTitle: "This is a title",
cityInfo: {
name: "shanghai",
text: "上海",
},
cityData: [
{
name: "beijing",
text: "北京",
},
{
name: "shanghai",
text: "上海",
},
{
name: "guangzhou",
text: "广州",
},
],
};
changeCity(cityInfo) {
this.setState({
cityInfo,
});
}
render() {
return (
<>
}
>
{this.state.cityInfo.text}
>
);
}
}
class Header extends React.Component {
render() {
return (
{this.props.text}
{this.props.citySelector}
);
}
}
class Selector extends React.Component {
render() {
return (
);
}
}
contextType
-
class
的静态属性 -
contextType
->React.createContext()
->Context
对象 -
this
->context
->CityContext
- 在生命周期函数和
render
函数中都可以访问 - 语义不太好
static contextType = CityContext;
componentDidMount() {
console.log(this.context);
}
render() {
console.log(this.context);
}
案例3
// index.jsx
import Home from "./views/Home";
import { btnStyle } from "./config";
import { BtnStyeContext, LoginStatusContext } from "./context_comps/context";
class App extends React.Component {
state = {
style: btnStyle.success,
loginStatus: false,
};
doClick(e) {
console.log(e.target.textContent);
}
login() {
this.setState({
loginStatus: !this.state.loginStatus,
});
}
render() {
return (
);
}
}
ReactDOM.render( , document.querySelector("#app"));
// Home.jsx
import { BtnStyeContext, LoginStatusContext } from "../context_comps/context";
import Header from "../components/Header";
import Main from "../components/Main";
import Footer from "../components/Footer";
export default class Home extends React.Component {
render() {
return (
);
}
}
// Header.jsx
import { LoginStatusContext } from "../context_comps/context";
import StButton from "./StButton";
export default class Header extends React.Component {
render() {
return (
{({ status, login }) => (
Header
Header({status ? " 已登录" : " 未登录"})
)}
);
}
}
// Main.jsx
import { LoginStatusContext } from "../context_comps/context";
import StButton from "./StButton";
export default class Main extends React.Component{
render() {
return (
{({ status, login }) => (
Main
Main({status ? " 已登录" : " 未登录"})
)}
);
}
}
// Footer.jsx
import { LoginStatusContext } from "../context_comps/context";
import StButton from "./StButton";
export default class Footer extends React.Component {
render() {
return (
{({ status, login }) => (
Footer
Footer({status ? " 已登录" : " 未登录"})
)}
);
}
}
// StButton.jsx
import { BtnStyeContext } from "../context_comps/context";
export default class StButton extends React.Component {
render() {
return (
// {({ style, doClick }) => (
//
// )}
);
}
}
// context.js
// 提供 context
import { btnStyle } from "../config";
const BtnStyeContext = React.createContext({
style: btnStyle.primary,
doClick: () => {},
});
const LoginStatusContext = React.createContext({
status: false,
login: () => {},
});
export { BtnStyeContext, LoginStatusContext };
// btnStyle
export const btnStyle = {
primary: {
color: "#fff",
backgroundColor: "blue",
},
success: {
color: "#fff",
backgroundColor: "green",
},
warning: {
color: "#000",
backgroundColor: "orange",
},
danger: {
color: "#fff",
backgroundColor: "red",
},
}
Fragment 和短语法应用
React.Fragment
组件,和 Document.createDocumentFragment()
类似,不会在原有 Dom
结构中增加冗余标签
现阶段,Fragment
组件除了 key
属性,不支持其他任何属性
短语法不支持 Key
,和其他任何语法
<>xxx>
class Table extends React.Component {
render() {
return (
Private Infomation
);
}
}
class TableHeader extends React.Component {
state = {
headers: ["Name", "ID", "Age"],
};
render() {
return (
{this.state.headers.map((item, index) => (
{item}
))}
);
}
}
class TableBody extends React.Component {
state = {
info: [
{
name: "zsss",
id: "897",
age: "177",
},
],
};
render() {
return (
{this.state.info.map((item) => (
{item.name}
{item.id}
{item.age}
))}
);
}
}
class App extends React.Component {
render() {
return
;
}
}