Context

初识 Context

.
├── App.jsx # 入口
├── Main.jsx # 主页面
├── components
│   ├── BottomNav # 底部
│   │   ├── Item.jsx
│   │   ├── index.css
│   │   └── index.jsx
│   └── Header # 顶部
│       ├── index.css
│       └── index.jsx
└── context.js # context

context.js

/**
 * ThemeContext -
 *  Provider 供应方
 *  Consumer 消费方(使用方)
 */

const ThemeContext = React.createContext('black');
export {
  ThemeContext
}

App.jsx

import Main from './Main';

import { ThemeContext } from './context';
class App extends React.Component {
  state = {
    theme: 'orange'
  }
  changeTheme(theme) {
    this.setState({
      theme
    })
  }
  render() {
    return (
      <ThemeContext.Provider value={ this.state.theme }>
        <Main changeTheme={ this.changeTheme.bind(this) } />
      </ThemeContext.Provider>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'));

Main.jsx

import Header from './components/Header/index';
import BottomNav from './components/BottomNav/index';
class Main extends React.Component {
  state = {
    navData: [
      '第①',
      '第②',
      '第③',
      '第④'
    ]
  }
  render() {
    return (
      <>
        <Header>这是标题</Header>
        {/* style外边 {} 是 JSX 语法,里边 {} 是 style 样式对象 */}
        <div style={{ marginTop: 88 + 'px' }}>
          <button onClick={ () => this.props.changeTheme('black') }>Black</button>
          <button onClick={ () => this.props.changeTheme('red') }>Red</button>
          <button onClick={ () => this.props.changeTheme('orange') }>Orange</button>
          <button onClick={ () => this.props.changeTheme('purple') }>Purple</button>
        </div>
        <BottomNav
          data={ this.state.navData }
        />
      </>
    )
  }
}
export default Main;

components/BottomNav/Item.jsx

import { ThemeContext } from '../../context';
class Item extends React.Component {
  render() {
    const { item, index } = this.props;
    return (
      <ThemeContext.Consumer>
        {
          (theme) =>
            <div className={ !index ? `item active-${theme}` : 'item' }>{ item} </div>
        }
      </ThemeContext.Consumer>
    )
  }
}
export default Item;

components/BottomNav/index.jsx

import NavItem from './Item';
import './index.css';
class BottomNav extends React.Component {
  render() {
    return (
      <div className="bottom-nav">
        {
          this.props.data.map((item, index) => {
            return (
              <NavItem
                item={ item }
                index={ index }
                key={ index }
              />
            )
          })
        }
      </div>
    )
  }
}
export default BottomNav;

components/BottomNav/index.css

.bottom-nav {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 44px;
  background-color: #efefef;
}

.bottom-nav .item {
  float: left;
  width: 25%;
  height: 100%;
  text-align: center;
  line-height: 44px;
  font-size: 14px;
  color: #999;
}

.bottom-nav .item.active-black {
  color: #000;
}
.bottom-nav .item.active-red {
  color: red;
}
.bottom-nav .item.active-orange {
  color: orange;
}
.bottom-nav .item.active-purple {
  color: purple;
}

components/Header/index.jsx

import './index.css';
import { ThemeContext } from '../../context';
class Header extends React.Component {
  render() {
    return (
      <ThemeContext.Consumer>
        {
          (theme) =>
          <header className={ `header ${theme}`}>{ this.props.children }</header>
        }
      </ThemeContext.Consumer>

    )
  }
}
export default Header;

Components/Header/index.css

.header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 44px;
  background-color: #000;

  text-align: center;
  color: #fff;
  line-height: 44px;
}

.header.black {
  background-color: #000;
  color: #fff;
}

.header.red {
  background-color: red;
  color: #fff;
}

.header.orange {
  background-color: orange;
  color: #000;
}

.header.purple {
  background-color: purple;
  color: #fff;
}