Context 共享数据
为避免太多层数据没必要的props传递,16.3版本设计了context组件数据共享
【案例】点击不同主题按钮切换下方区域样式
1.在src下新建theme-context.js组件,用于存放共享数据(中转站)
theme-context.js组件代码如下,定义一个Context将它导出,供子组件导入
import React from 'react'
const ThemeContext =React.createContext()
export default ThemeContext复制代码
2.父组件引入import ThemeContext from './theme-context'
3.在父组件里,将要传值的视图板块,用<ThemeContext>标签包裹起来,
其中两个a标签是要点击变换的按钮,
render() {
return (
<ThemeContext.Provider>
<div className="App">
<a href="#theme-switcher"
className="btn btn-light"
>浅色主题</a>
<a href="#theme-switcher"
className="btn btn-secondary"
>深色主题</a>
</div>
</ThemeContext.Provider>
);复制代码
4.在父组件里,定义共享数据themes,有两条数据light和dark,数据里分别是css样式
const themes = {
light:{
className:'btn btn-primary',
bgColor:'#eeeeee',
color:'#000'
},
dark:{
className: 'btn btn-light',
bgColor: '#222222',
color:'#fff'
},
}复制代码
5.在components文件夹里新建ThemeBar.js组件,用于展示样式变换
首先在此组件引入import ThemeContext from '../theme-context'
将组件要接收共享数据的模块用<ThemeContext>标签包裹,并.Consumer导入
return(
<ThemeContext.Consumer>
{
theme =>{
//console.log(theme)
return(
<div
className="alert mt-5"
}}
>
样式区域
<button>
样式按钮
</button>
</div>
)
}
}
</ThemeContext.Consumer>
)复制代码
6.在父组件的标签里设置value将themes数据导出,
给a标签添加点击事件changTheme,参数分别为light和dark
<ThemeContext.Provider value={themes[this.state.theme]}>
<div className="App">
<a href="#theme-switcher"
className="btn btn-light"
onClick={()=>{this.changeTheme('light')}}
>浅色主题</a>
<a href="#theme-switcher"
className="btn btn-secondary"
onClick={()=>{this.changeTheme('dark')}}
>深色主题</a>
<ThemeBar/>
</div>
</ThemeContext.Provider>
);复制代码
7.在state中设置theme默认为light样式
constructor(props){
super(props)
this.state = {
theme:"light"
}
}复制代码
8.给changTheme事件绑定this
constructor(props){
super(props)
this.state = {
theme:"light"
}
this.changeTheme = this.changeTheme.bind(this)
}复制代码
9.定义changTheme事件,点击哪个a切换至相应参数下的数据
changeTheme(theme){
this.setState({
theme,
})
}复制代码
10.在展示样式的组件中,给div绑定style,获取父元素theme数据下的bgColor等数据
return(
<ThemeContext.Consumer>
{
theme =>{
//console.log(theme)
return(
<div
className="alert mt-5"
style={{ backgroundColor:theme.bgColor,
color:theme.color,
}}
>
样式区域
<button className={theme.className}>
样式按钮
</button>
</div>
)
}
}
</ThemeContext.Consumer>
)复制代码
就做到了一个视图展示层 共享同一份 不同元素的数据
点击切换组件 修改同一个视图模板下的不同css样式
所有代码:
App.js下:
import React, { Component } from 'react';
import './App.css';
import ThemeBar from './components/ThemeBar'
import ThemeContext from './theme-context'
const themes = {
light:{
className:'btn btn-primary',
bgColor:'#eeeeee',
color:'#000'
},
dark:{
className: 'btn btn-light',
bgColor: '#222222',
color:'#fff'
},
}
class App extends Component {
constructor(props){
super(props)
this.state = {
theme:"light"
}
this.changeTheme = this.changeTheme.bind(this)
}
changeTheme(theme){
this.setState({
theme,
})
}
render() {
return (
<ThemeContext.Provider value={themes[this.state.theme]}>
<div className="App">
<a href="#theme-switcher"
className="btn btn-light"
onClick={()=>{this.changeTheme('light')}}
>浅色主题</a>
<a href="#theme-switcher"
className="btn btn-secondary"
onClick={()=>{this.changeTheme('dark')}}
>深色主题</a>
<ThemeBar/>
</div>
</ThemeContext.Provider>
);
}
}
export default App;
复制代码
ThemeBar.js下:展示样式变换组件
import React from 'react'
import ThemeContext from '../theme-context'
const ThemeBar = ()=>{
return(
<ThemeContext.Consumer>
{
theme =>{
//console.log(theme)
return(
<div
className="alert mt-5"
style={{ backgroundColor:theme.bgColor,
color:theme.color,
}}
>
样式区域
<button className={theme.className}>
样式按钮
</button>
</div>
)
}
}
</ThemeContext.Consumer>
)
}
export default ThemeBar复制代码
theme-context.js下:
import React from 'react'
const ThemeContext =React.createContext()
export default ThemeContext复制代码
最终样式:默认为light主题,点击对应按钮切换对应主题