react中的context

对react context的理解:

为什么使用context

在React中,数据传递一般使用props传递数据,维持单向数据流,这样可以让组件之间的关系变得简单并且可预测,但是单项数据流在某些场景中并不适用。单纯一对的父子组件传递并无问题,但要是组件之间层层依赖深入,props就需要层层传递。显然,这样做太繁琐了

context是什么

Context 提供了一种在组件之间共享值的方式,而不必显式地通过组件树的层层传递 props.

可以把context当做是特定一个组件树内共享的store,用来做数据传递。简单说就是,当你不想在组件树中通过逐层传递props或者state的方式来传递数据时,可以使用Context来实现跨层级的组件数据传递

context怎么样运行

JS的代码块在执行期间,会创建一个相应的作用域链,这个作用域链记录着运行时JS代码块执行期间所能访问的活动对象,包括变量和函数,JS程序通过作用域链访问到代码块内部或者外部的变量和函数

假如以JS的作用域链作为类比,React组件提供的Context对象其实就好比一个提供给子组件访问的作用域,而Context对象的属性可以看成作用域上的活动对象,由于组件的 Context 由其父节点链上所有组件通过getChildContext ()返回的Context对象组合而成,所以,组件通过Context是可以访问到其父组件链上所有节点组件提供的context属性

context中的API

createContext():
用于创建context对象(上下文),需要一个defaultValue的参数,并返回一个包含Provider(提供者),以及Consumer(消费者)的对象。

Provider:
提供者,提供数据。接收一个将要被往下层层传递的props,该值需在组件树最顶层设置。一个Provider可以关联到多个Consumers。这是一个顶层用于提供context的组件,包含一个value的props,value是实际的context数据。

Consumer:
消费者,使用者,接收一个函数作为子节点,函数接收当前 context 的值。这是一个底层用于获取context的组件,需要一个函数作为其子元素,该函数包含一个value的参数,这个参数就是上层所传递context value

React中context的使用方法

// 引入React
import React, {Component} from 'react';
// 引入样式
import './App.css';

/*
* 详细说明:定义了三个组件:分别为App/AppChild/AppChildChild
* 组件关系:App -> AppChild 父子; App -> AppChildChild 祖;AppChild -> AppChildChild 父子;
* 通过下面案例你将领略context的使用方法
* 使用方法总结:
* 1.先创建一个Context容器对象,可以进行结构Provider及Consumer方便之后的简单应用。
* 2.包裹要用的组件,给谁用就在谁的外面包裹,使用属性关键字value进行传值,value不可改变。
* 3.在哪里使用就在哪里声明,static contextType = 容器对象名字;
* 4.使用 this.content获取
* 注意上述方法只限于类式组件,如果你使用的是函数式组件,那么你应该用下面的方式去做
* <Consumer>
*   {
*        value => {
*        }
*    }
* </Consumer>
***/

// 创建一个Context容器对象,注意开头大写
const MyContext = React.createContext()
// 拿出Provider及Consumer
const {Provider, Consumer} = MyContext;
// 定义一个祖组件
class App extends Component {
    state = {
        username: 'Tom',
        age: 20
    }
    render() {
        const {username, age} = this.state;
        return (
            <div className="App">
                <h3>我是App组件</h3>
                <h4>我的名字:{username}</h4>
                {/*利用props给子组件AppChild传值*/}
                {/*给谁用就用Provider包裹*/}
                {/*<Provider value={username}>
                    <AppChild username={username}/>
                </Provider>*/}
                <Provider value={{username, age}}>
                    <AppChild username={username}/>
                </Provider>
            </div>
        );
    }
}

// 父级组件
class AppChild extends Component {
    render() {
        const {username} = this.props;
        return (
            <div className="AppChild">
                <h3>我是AppChild组件</h3>
                <h4>我接收来自App组件的名字是:{username}</h4>
                <AppChildChild/>
            </div>
        );
    }
}

// 子组件-类式声明
/*class AppChildChild extends Component {
    // 声明context
    static contextType = MyContext;
    render() {
        const {username, age} = this.context;
        return (
            <div className="AppChildChild">
                <h3>我是AppChildChild组件</h3>
                <h4>我接收来自App组件的名字是:{username},年龄:{age}</h4>
            </div>
        );
    }
}*/
// 子组件-函数式声明
function AppChildChild() {
    return (
        <div className="AppChildChild">
            <h3>我是AppChildChild组件</h3>
            <h4>
                <Consumer>
                    {
                        value => {
                            return `我接收来自App组件的名字是:${value.username},年龄:${value.age}`
                        }
                    }
                </Consumer>
            </h4>
        </div>
    )
}
export default App;

为什么React并不推荐优先考虑使用Context?

  • Context目前还处于实验阶段,可能会在后面的发行版本中有很大的变化,事实上这种情况已经发生了,所以为了避免给今后升级带来大的影响和麻烦,不建议在app中使用context
  • 尽管不建议在app中使用context,但是独有组件而言,由于影响范围小于app,如果可以做到高内聚,不破坏组件树之间的依赖关系,可以考虑使用context
  • 对于组件之间的数据通信或者状态管理,有效使用props或者state解决,然后再考虑使用第一方的成熟库进行解决,以上的方法都不是最佳的方案的时候,在考虑context
  • context的更新需要通过setState() 触发,但是这并不是很可靠的,Context支持跨组件的访问,但是如果中间的子组件通过一些方法不影响更新,比如 shouldComponentUpdate() 返回false 那么不能保证Context的更新定可以使用Context的子组件,因此,Context的可靠性需要关注
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值