2022即将到来,前端发展非常迅速,现在的前端已经不再是写写简单的页面了,伴随着web大前端,工程化越来越火,也出现了很多框架。很多公司也不单单是使用单一的框架了,作为前端开发国内最火的两大框架,都是必须要掌握的。所以,我决定在这疫情肆虐的年底把React学习一下,也为自己将来找工作多一分竞争力...
学习阶段,如有不对之处,欢迎评论区留言,我及时更正
本文已连载,其它章节传送门⬇️
跨组件通信Context
父子组件的通信我们可以通过Props传递,但如果嵌套很多层的组件需要通信,我们需要一层一层传递到后代组件,这使得通信变得异常繁琐,于是React通过订阅Context实现了跨组件的通信,无需一层层传递。
不过使用Context我们需要注意以下几点:
-
函数组件没有context属性
-
组件如果订阅了context,会从离自身最近的匹配的Provier中读取当前context值
-
一个Provider 可以和多个订阅组件有对应关系,多个Provider 也可以嵌套使用,里层覆盖外层数据
-
当Provider value值发生变化的时候,所有订阅此context的组件都会重新渲染
context的Provider
// 创建Context
const UserContext = React.createContext({
nickName: '小明',
userId: 'jd1557834'
});
class Son extends Component {
static contextType = UserContext
render() {
console.log(this.context)
return (
<div>
<p>昵称:{this.context.nickName}</p>
<p>账号:{this.context.userId}</p>
</div>
)
}
}
class Person extends Component {
render() {
return (
<div>
<Son></Son>
</div>
)
}
}
class App extends Component {
constructor(props) {
super(props)
this.state = {
nickName: '小红',
userId: 'jd1557834'
}
}
render() {
return (
<div>
<UserContext.Provider value={this.state}>
<Person />
</UserContext.Provider>
</div>
)
}
}
创建App
Person
Son
三个组件,它们的层级关系为:App
>Person
>Son
。想要使用Context,首先 我们需要调用React.createContext 创建一个context,可以给一个初始值。每个context都会返回一个Provider 组件 ,供其它后代组件订阅context的变化~把传递数据的组件包裹在Provider 组件内部,此时把我们需要传递的数据放在value属性里。 OK,这时再看我们的后代子孙组件,通过 static 关键字指定此组件的contextType
,把我们创建的context赋值给此组件的context,组件内部就可以通过context接收到数据了。
context的Consumer
💡问题:如果子组件是函数组件,没有context属性,怎么办?
function Son() {
return(
<UserContext.Consumer>
{
value => {
return(
<div>
<p>昵称:{value.nickName}</p>
<p>账号:{value.userId}</p>
</div>
)
}
}
</UserContext.Consumer>
)
}
context除了Provider
还会返回一个Consumer组件,用来解决函数组件没有context属性的问题,我们需要把组件的内容包裹在Consumer 组件内,并在组件内通过箭头函数的入参拿到传递的value,这样我们就可以直接在组件内使用value。
多个context
💡问题:如果我们有多个context需要共享数据怎么办?
创建一个新的context
const MobileContext = React.createContext({
mobileNumber: 15138994429
})
修改APP根组件
<UserContext.Provider value={this.state}>
<MobileContext.Provider value={{mobileNumber: 15592899231}}>
<Person />
</MobileContext.Provider>
</UserContext.Provider>
修改son子组件
function Son() {
return(
<UserContext.Consumer>
{
value => {
return(
<MobileContext.Consumer>
{
them => {
return(
<div>
<p>昵称:{value.nickName}</p>
<p>账号:{value.userId}</p>
<p>手机号码:{them.mobileNumber}</p>
</div>
)
}
}
</MobileContext.Consumer>
)
}
}
</UserContext.Consumer>
)
}
多个context需要提供的话,就会变得异常繁琐,嵌套层级过多,代码阅读性也变得很差了