react之context

你可能永远都不会用上react的context特性,如果你想让你的应用更稳定,别使用context  ---- 摘自官网

在过去很长一段时间里面,React.js 的 context 一直被视为一个不稳定的、危险的、可能会被去掉的特性而不被官网文档所记载。但是全世界的第三方库都在用使用这个特性,直到了 React.js 的 v0.14.1 版本,context 才被官方文档所记录。除非你觉得自己的 React.js 水平已经比较炉火纯青了,否则你永远不要使用 context。就像你学 JavaScript 的时候,总是会被提醒不要用全局变量一样,React.js 的 context 其实像就是组件树上某颗子树的全局变量。   ---- 摘自react小书   作者:胡子大哈 原文链接: http://huziketang.com/books/react/lesson29

 

在实际开发中,我们常常有许多组件,父组件里面有子组件  子组件里面又有它自己的子组件,而在父子组件中 我们通过props一层层传递状态给子组件,但是我们的组件树很深的话,一层层用props传下去,那真的是太痛苦了,React.js 的 context 就是这么一个东西,某个组件只要往自己的 context 里面放了某些状态,这个组件之下的所有子组件都直接访问这个状态而不需要通过中间组件的传递。一个组件的 context 只有它的子组件能够访问,它的父组件是不能访问到的,你可以理解每个组件的 context 就是瀑布的源头,只能往下流不能往上飞。

看代码:

  父组件: App.js   

import React , { Component } from 'react';
import PropTypes from 'prop-types'
import Header from './Header'
import Main from './Main';
class App extends Component {
    static childContextTypes = {
        themeColor: PropTypes.string
    };
    constructor () {
        super()
        this.state = { themeColor: 'red' }
    }
    getChildContext () {
        return { themeColor: this.state.themeColor }
    }
    componentWillMount(){
        this.setState({
            themeColor:'pink'
        })
    }
    render(){
        return (
            <div>
                <Header />
                <Main />
            </div>
        )
    }
}
export default App;

  父组件下面的两个子组件 Header Main

  Header:

import React , { Component } from 'react';
import Title from './Title'
class Header extends Component {
    render(){
        return (
            <div>
                <h2>This is header</h2>
                <Title/>
            </div>
        )
    }
}
export default Header

  Main:

import React , { Component } from 'react';
import Content from './Content'
class Main extends Component {
    render(){
        return (
            <div>
                <h2>This is Main</h2>
                <Content />
            </div>
        )
    }
}
export default Main;

  Header下面的子组件: Title

import React , { Component } from 'react';
import Ahao from './Ahao'
class Title extends Component {
    render(){
        return (
            <div>
               <h2>React小书标题</h2>
                <Ahao />
            </div>
        )
    }
}
export default Title;

  Header下面的子组件Title组件下面的子组件 Ahao

import React , { Component } from 'react';
import PropTypes from 'prop-types'
class Ahao extends Component {
    static contextTypes = {
        themeColor: PropTypes.string
    }
    render(){
        return (
            <div style={{color:this.context.themeColor}}>
                你若成风
            </div>
        )
    }
}
export default Ahao;

 Main下面的子组件:Content

import React , { Component } from 'react';
class Content extends Component {
    render(){
        return (
            <div>
                <h2>React小书内容</h2>
            </div>
        )
    }
}
export default Content;

  

代码看上去很多,但很简单 其实重要的就是 App组件 Ahao组件  其他组件主要是用于层层嵌套

先看App: 

  首先:1.

static childContextTypes = { 
  themeColor: PropTypes.string      
}

  !!! 这行代码先说明 这是必须要写的 , 给App组件定义一个静态方法  childContextTypes  它的作用其实 propsType 验证组件 props 参数的作用类似。不过它是验证 getChildContext 返回的对象。为什么要验证 context,因为 context 是一个危险的特性,按照 React.js 团队的想法就是,把危险的事情搞复杂一些,提高使用门槛人们就不会去用了。如果你要给组件设置 context,那么 childContextTypes 是必写的。

2. 

constructor () {
        super();
        this.state = { themeColor: 'red' }
    }
    getChildContext () {
        return { themeColor: this.state.themeColor }
    }

getChildContext 这个方法就是设置 context 的过程,它返回的对象就是 context ,所有的子组件都可以访问到这个对象。我们用 this.state.themeColor 来设置了 context 里面的 themeColor

context是已经设置完成了

 

再看Ahao组件  Ahao组件 是App组件中的Header组件中的Title组件的子组件,我们直接用context直接拿到App组件的状态 themeColor;

Ahao组件中的一段代码:

class Ahao extends Component {
    static contextTypes = {
        themeColor: PropTypes.string
    }
    render(){
        return (
            <div style={{color:this.context.themeColor}}>
                你若成风
            </div>
        )
    }
}

1.首先我们还是要定义静态方法确定themeColor是个字符串
2.直接用context API设置 style={{color:this.context.themeColor}} // ok了

 

   

界面就是这样了  Ahao文字中的样式直接就改变了  themeColor状态就拿到了。就这样简单

 

如果我们要改颜色,只需要在 Index 里面 setState 就可以了,子组件会重新渲染,渲染的时候会重新取 context 的内容,例如我们给 Index 调整一下颜色:

  componentWillMount () {
    this.setState({ themeColor: 'green' })
  }

那么 Title 里面的字体就会显示绿色。我们可以如法炮制孙子组件 Content,或者任意的 Index 下面的子组件。让它们可以不经过中间 props 的传递获就可以获取到由 Index 设定的 context 内容。

 

结尾:

一个组件可以通过 getChildContext 方法返回一个对象,这个对象就是子树的 context,提供 context 的组件必须提供 childContextTypes 作为 context 的声明和验证。

如果一个组件设置了 context,那么它的子组件都可以直接访问到里面的内容,它就像这个组件为根的子树的全局变量。任意深度的子组件都可以通过 contextTypes 来声明你想要的 context 里面的哪些状态,然后可以通过 this.context 访问到那些状态。

context 打破了组件和组件之间通过 props 传递数据的规范,极大地增强了组件之间的耦合性。而且,就如全局变量一样,context 里面的数据能被随意接触就能被随意修改,每个组件都能够改 context 里面的内容会导致程序的运行不可预料。

但是这种机制对于前端应用状态管理来说是很有帮助的,因为毕竟很多状态都会在组件之间进行共享,context 会给我们带来很大的方便。一些第三方的前端应用状态管理的库(例如 Redux)就是充分地利用了这种机制给我们提供便利的状态管理服务。但我们一般不需要手动写 context,也不要用它,只需要用好这些第三方的应用状态管理库就行了。

 

 

本文摘自 --- react小书  

作者:胡子大哈

原文链接: http://huziketang.com/books/react/lesson29

 

 

 

  

posted @ 2018-02-04 11:30  ahaowh  阅读(153)  评论(0)    收藏  举报