zoukankan      html  css  js  c++  java
  • React Context(执行上下文)

    一、Context 解决什么问题

    React是单向数据流,数据是从上往下单向传递的,每个组件都可以接收父组件的属性和状态,也可以把属性和状态向下传递给子组件,但是当层级特别多的时候就会变得非常繁琐。Context 提供了一种在组件之间共享此类值得方式,而不必逐层传递。它主要是用来解决祖先组件后代组件传递数据的问题(prop drilling)。方便组件之间跨层级传递数据。

    举个例子:用户登录之后,很多组件需要拿到用户相关信息,如果按照prop传递的方式获取,会变得异常繁琐,而且很难判断数据的真正来源。使用Context,就可以在Provider的后代组件的任意位置,都可以Consumer数据。

    二、如何使用

    • 1. 通过createContext创建Context
    • 2. 使用Context.Provider组件发布数据(通过给Context.Provider传递value属性)。
    • 3. 如果是函数组件,那么所有后代组件,都可以通过Context.Consumer消费数据
    • 4. 如果是类组件,那么所有的后代组件都需要通过  this.context.xxx 来获取

    1.类组件的context

    import React from "react";
    import ReactDOM from "react-dom";
    
    let ThemeContext = React.createContext();
    
    class Content extends React.Component {
      //取父组件传递过来得值
      //先定义一个静态属性contextType 通过this.context.color拿到值
      static contextType = ThemeContext
      render() {
        return <div style={{ border: `1px solid ${this.context.color}` }}>内容</div>;
      }
    }
    class Main extends React.Component {
      //取父组件传递过来得值
      //先定义一个静态属性contextType 通过this.context.color拿到值
      static contextType = ThemeContext
      render() {
        return (
          <div style={{ border: `1px solid ${this.context.color}` }}>
            子Main
            <Content}></Content>
          </div>
        );
      }
    }
    class Title extends React.Component {
      //取父组件传递过来得值
      //先定义一个静态属性contextType 通过this.context.color拿到值
      static contextType = ThemeContext
      render() {
        return <div style={{ border: `1px solid ${this.context.color}` }}>标题</div>;
      }
    }
    class Header extends React.Component {
      //取父组件传递过来得值
      //先定义一个静态属性contextType 通过this.context.color拿到值
      static contextType = ThemeContext
      render() {
        return (
          <div style={{ border: `1px solid ${this.context.color}` }}>
            子Header
            <Title></Title>
          </div>
        );
      }
    }
    class Panel extends React.Component {
      state = { color: "green" };
      render() {
        let colorvalue = { color: this.state.color };
        // Provider 表示提供者,负责向下层所有得组件提供数据value 它得所有子组件都可以通过拿到value值
        return (
          <ThemeContext.Provider value={colorvalue}> 
            <div style={{ border: `1px solid ${this.state.color}`,  `200px` }}>
              Panel
              <Header></Header>
              <Main></Main>
            </div>
          </ThemeContext.Provider>
        );
      }
    }
    
    ReactDOM.render(<Panel></Panel>, document.getElementById("root"));

    修改数据:

    import React from "react";
    import ReactDOM from "react-dom";
    
    let ThemeContext = React.createContext();
    
    class Content extends React.Component {
      //取父组件传递过来得值
      //先定义一个静态上下文类型contextType 通过this.context.value拿到值
      static contextType = ThemeContext
      render() {
        return (
        <div style={{ border: `1px solid ${this.context.color}` }}>
          内容
          <button onClick={() => this.context.changeColor('red')}>变红</button>
          <button onClick={() => this.context.changeColor('green')}>变绿</button>
          </div>
          )
      }
    }
    class Main extends React.Component {
      //取父组件传递过来得值
      //先定义一个静态上下文类型contextType 通过this.context.value拿到值
      static contextType = ThemeContext
      render() {
        return (
          <div style={{ border: `1px solid ${this.context.color}`}}>
            子Main
            <Content style={{ border: `1px solid ${this.context.color}` }}></Content>
          </div>
        );
      }
    }
    class Title extends React.Component {
      //取父组件传递过来得值
      //先定义一个静态上下文类型contextType 通过this.context.value拿到值
      static contextType = ThemeContext
      render() {
        return <div style={{ border: `1px solid ${this.context.color}` }}>标题</div>;
      }
    }
    class Header extends React.Component {
      //取父组件传递过来得值
      //先定义一个静态上下文类型contextType 通过this.context.value拿到值
      static contextType = ThemeContext
      render() {
        return (
          <div style={{ border: `1px solid ${this.context.color}` }}>
            子Header
            <Title></Title>
          </div>
        );
      }
    }
    class Panel extends React.Component {
      state = { color: "green" };
      changeColor = (color) => {
        this.setState({color})
      }
      render() {
        let colorvalue = { color: this.state.color, changeColor: this.changeColor };
        // Provider 表示提供者,负责向下层所有得组件提供数据value 它得所有子组件都可以通过拿到value值
        return (
          <ThemeContext.Provider value={colorvalue}> 
            <div style={{ border: `1px solid ${this.state.color}`,  `200px` }}>
              Panel
              <Header></Header>
              <Main></Main>
            </div>
          </ThemeContext.Provider>
        );
      }
    }
    
    ReactDOM.render(<Panel></Panel>, document.getElementById("root"));

       

    任何一个后代组件都可以修改数据,这会导致所有的后代组件都会获取到修改后的值,这显然是不可取的,最好还是由发布者修改。

    2.函数组件的context

    import React from "react";
    import ReactDOM from "react-dom";
    
    let ThemeContext = React.createContext();
    
    
    function Content (props){
      //Consumer 消费者 消费上下文中的value,通过value.xxx来获取发布的数据
      return (
        <ThemeContext.Consumer>
          {
            (value) => (
              <div style={{ border: `1px solid ${value.color}` }}>
                内容
                <button onClick={() => value.changeColor('red')}>变红</button>
                <button onClick={() => value.changeColor('green')}>变绿</button>
              </div>
            )
          }
        </ThemeContext.Consumer>
      )
    }
    
    function Main (props){
      //Consumer 消费者 消费上下文中的value,通过value.xxx来获取发布的数据
      return (
        <ThemeContext.Consumer>
          {
            (value) => (
              <div style={{ border: `1px solid ${value.color}`}}>
                子Main
                <Content style={{ border: `1px solid ${value.color}` }}></Content>
              </div>
            )
          }
        </ThemeContext.Consumer>
      )
    }
    
    function Title (props){
      //Consumer 消费者 消费上下文中的value,通过value.xxx来获取发布的数据
      return (
        <ThemeContext.Consumer>
          {
            (value) => (
              <div style={{ border: `1px solid ${value.color}` }}>标题</div>
            )
          }
        </ThemeContext.Consumer>
      )
    }
    function Header (props){
      //Consumer 消费者 消费上下文中的value,通过value.xxx来获取发布的数据
      return (
        <ThemeContext.Consumer>
          {
            (value) => (
              <div style={{ border: `1px solid ${value.color}` }}>
                子Header
                <Title></Title>
              </div>
            )
          }
        </ThemeContext.Consumer>
      )
    }
    
    class Panel extends React.Component {
      state = { color: "green" };
      changeColor = (color) => {
        this.setState({color})
      }
      render() {
        let colorvalue = { color: this.state.color, changeColor: this.changeColor };
        // Provider 表示提供者,负责向下层所有得组件提供数据value 它得所有子组件都可以通过拿到value值
        return (
          <ThemeContext.Provider value={colorvalue}> 
            <div style={{ border: `1px solid ${this.state.color}`,  `200px` }}>
              Panel
              <Header></Header>
              <Main></Main>
            </div>
          </ThemeContext.Provider>
        );
      }
    }
    
    ReactDOM.render(<Panel></Panel>, document.getElementById("root"));

    可以看到函数组件需要通过context.Consumer来消费上下文中的value,并且通过value.xxx来获取发布的数据

    三、context的底层实现原理

    不积跬步无以至千里
  • 相关阅读:
    .net的一致性哈希实现
    一次基于etcd的分布式锁自动延时失败问题的排查
    一次kubernetes资源文件创建失败的排查
    去除右键菜单中的图形属性
    三款实用的视频格式转换工具
    使用iframe设置frameset的高度
    IIS中asp网站播放flv视频技术
    Joomla3.1.1在64位win7下安装
    64位win7旗舰版搭建apache+php+mysql开发环境[转]
    Windows下实战Apache+PHP [转]
  • 原文地址:https://www.cnblogs.com/lyt0207/p/12688874.html
Copyright © 2011-2022 走看看