zoukankan      html  css  js  c++  java
  • 对react的context的研究

    Context被翻译为上下文,在编程领域,这是一个经常会接触到的概念,React中也有。

    在React的官方文档中,Context被归类为高级部分(Advanced),属于React的高级API,但官方并不建议在稳定版的App中使用Context。

    不过,这并非意味着我们不需要关注Context。事实上,很多优秀的React组件都通过Context来完成自己的功能,比如react-redux的<Provider />,就是通过Context提供一个全局态的store,拖拽组件react-dnd,通过Context在组件中分发DOM的Drag和Drop事件,路由组件react-router通过Context管理路由状态等等。在React组件开发中,如果用好Context,可以让你的组件变得强大,而且灵活。
     简单说就是,当你不想在组件树中通过逐层传递props或者state的方式来传递数据时,可以使用Context来实现跨层级的组件数据传递。
     
    使用Context,可以跨越组件进行数据传递。
     
    对于父组件,也就是Context生产者,需要通过一个静态属性childContextTypes声明提供给子组件的Context对象的属性,并实现一个实例getChildContext方法,返回一个代表Context的纯对象 (plain object) 。

    而对于Context的消费者,通过如下方式访问父组件提供的Context
     

    子组件需要通过一个静态属性contextTypes声明后,才能访问父组件Context对象的属性,否则,即使属性名没写错,拿到的对象也是undefined

    对于无状态子组件(Stateless Component),可以通过如下方式访问父组件的Context

    通过静态方法React.createContext()创建一个Context对象,这个Context对象包含两个组件,<Provider /><Consumer />

    几个可以直接获取Context的地方

    实际上,除了实例的context属性(this.context),React组件还有很多个地方可以直接访问父组件提供的Context。比如构造方法:

    • constructor(props, context)

    比如生命周期:
    • componentWillReceiveProps(nextProps, nextContext)
    • shouldComponentUpdate(nextProps, nextState, nextContext)
    • componetWillUpdate(nextProps, nextState, nextContext)
    对于面向函数的无状态组件,可以通过函数的参数直接访问组件的Context
    const StatelessComponent = (props, context) => (
      ......
    )

    把Context当做组件作用域

    使用React的开发者都知道,一个React App本质就是一棵React组件树,每个React组件相当于这棵树上的一个节点,除了App的根节点,其他每个节点都存在一条父组件链。

    通过Context暴露数据或者API不是一种优雅的实践方案,尽管react-redux是这么干的。因此需要一种机制,或者说约束,去降低不必要的影响。

    通过childContextTypescontextTypes这两个静态属性的约束,可以在一定程度保障,只有组件自身,或者是与组件相关的其他子组件才可以随心所欲的访问Context的属性,无论是数据还是函数。因为只有组件自身或者相关的子组件可以清楚它能访问Context哪些属性,而相对于那些与组件无关的其他组件,无论是内部或者外部的 ,由于不清楚父组件链上各父组件的childContextTypes“声明”了哪些Context属性,所以没法通过contextTypes“申请”相关的属性。所以我理解为,给组件的作用域Context“带权限”,可以在一定程度上确保Context的可控性和影响范围。

    在开发组件过程中,我们应该时刻关注这一点,不要随意的使用Context

    • App级的数据共享

    App根节点组件提供的Context对象可以看成是App级的全局作用域,所以,我们利用App根节点组件提供的Context对象创建一些App级的全局数据。现成的例子可以参考react-redux,以下是<Provider />组件源码的核心实现:

    export function createProvider(storeKey = 'store', subKey) {
        const subscriptionKey = subKey || `${storeKey}Subscription`
    
        class Provider extends Component {
            getChildContext() {
              return { [storeKey]: this[storeKey], [subscriptionKey]: null }
            }
    
            constructor(props, context) {
              super(props, context)
              this[storeKey] = props.store;
            }
    
            render() {
              return Children.only(this.props.children)
            }
        }
    
        // ......
    
        Provider.propTypes = {
            store: storeShape.isRequired,
            children: PropTypes.element.isRequired,
        }
        Provider.childContextTypes = {
            [storeKey]: storeShape.isRequired,
            [subscriptionKey]: subscriptionShape,
        }
    
        return Provider
    }
    
    export default createProvider()
    App的根组件用<Provider />组件包裹后,本质上就为App提供了一个全局的属性store,相当于在整个App范围内,共享store属性。当然,<Provider />组件也可以包裹在其他组件中,在组件级的全局范围内共享store
    组件级的数据共享
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    TI科学家谈浮点DSP未来发展
    请爱护你的JTAG烧录口---记录
    程序猿必看
    富人与穷人的区别--转自红尘
    DSP已经英雄迟暮了吗?FPGA才是未来的大杀器?
    FPGA+ARM or FPGA+DSP?
    DDR3调试记录
    调试记录1
    有关FPGA
    Nginx常见配置说明
  • 原文地址:https://www.cnblogs.com/zhouyideboke/p/12605897.html
Copyright © 2011-2022 走看看