React之使用Context跨组件树传递数据

---------------------------------  讲解一 

原文:https://blog.csdn.net/xuxiaoping1989/article/details/78480758 

注意: 从 React v15.5 开始 ,React.PropTypes 助手函数已被弃用,我们建议使用 prop-types 库 来定义contextTypes。
2.1首先你需要通过在终端npm install prop-types安装一个叫prop-types的第三方包

getChildContext 定义在父组件中,指定子组件可以使用的信息
childContextTypes 定义在父组件中,getChildContext 指定的传递给子组件的属性需要先通过 childContextTypes 来指定,不然会产生错误
子组件需要通过 contextTypes 指定需要访问的元素。 contextTypes 没有定义, context 将是一个空对象。

父组件定义 

class Greeter extends Component{
    constructor(props){
        super(props)
        this.state={
            add:87,
            remove:88
        }
    }
    static childContextTypes = {
        add:T.number,
        remove:T.number
    }
    getChildContext() {
       const { add,remove} = this.state;
       return {
           add,
           remove
       }
    }
    render(){
        return(
            <div>
                <ComponetReflux/>
            </div>
        )
    }
}

子组件定义

class ComponetReflux extends Component{
    constructor(props){
        super(props)
        this.state={
            
        }
    }
    static contextTypes = {
        add:T.number,
        remove:T.number
    }
    render(){
        console.log(this.context)              //打印{add:87,remove:88}
        const {name,age} = this.state
        return (
            <div>测试context</div>
    )
    }
};

---------------------------------------------------------------  讲解二 

原文:https://blog.csdn.net/jimolangyaleng/article/details/77715862 

react推崇的是单向数据流,自上而下进行数据的传递,但是由下而上或者不在一条数据流上的组件之间的通信就会变的复杂。解决通信问题的方法很多,如果只是父子级关系,父级可以将一个回调函数当作属性传递给子级,子级可以直接调用函数从而和父级通信。

组件层级嵌套到比较深,可以使用上下文getChildContext来传递信息,这样在不需要将函数一层层往下传,任何一层的子级都可以通过this.context直接访问。

兄弟关系的组件之间无法直接通信,它们只能利用同一层的上级作为中转站。而如果兄弟组件都是最高层的组件,为了能够让它们进行通信,必须在它们外层再套一层组件,这个外层的组件起着保存数据,传递信息的作用,这其实就是redux所做的事情。

组件之间的信息还可以通过全局事件来传递。不同页面可以通过参数传递数据,下个页面可以用location.param来获取。其实react本身很简单,难的在于如何优雅高效的实现组件之间数据的交流。

今天我们就来熟悉下react的context数据传递
 

没有使用Context的情况下传递数据, 我们可以参考React的文档:  Context, 它是通过组件属性一级一级往下传递. 这种方式很麻烦, 如果组件树比较深, 必须在每一个路径上的节点都引入不必要的属性.
 

定义 Context 的根组件

import React      from 'react';
 
# React 15.5版本以后, 使用PropTypes需要引入外部库, 直接使用React.PropTypes 会抛警告
import PropTypes from 'prop-types';
 
# React Router V4版本要从 react-router-dom 导入需要的组件
import { Route, Link } from 'react-router-dom';
 
import { Row, Col, Menu, Icon, Dropdown, Layout} from 'antd';
const { Sider, Content } = Layout;
 
import UserList   from './UserList';
import UserDetail from './UserDetail';
import Sidebar    from '../_layouts/Sidebar';
 
const avatars = [
  "elyse.png",
  "kristy.png",
  "matthew.png",
];
 
const data = [];
for(let i = 0; i <= avatars.length; i++){
  data.push({key: i, name: '胡彦祖3',age: 42,address: '西湖区湖底公园1号'});
}
const columns = [
  { title: 'ID',dataIndex: 'key',key: 'key'},
  { title: '姓名',dataIndex: 'name',key: 'name', render: function(text, record, index) {
    return (<Link to={`/users/${index}`}><div style={{display: 'block'}}>{text}</div></Link>)
  }},
  { title: '年龄',dataIndex: 'age',key: 'age'},
  { title: '住址',dataIndex: 'address',key: 'address'},
  {
    title: 'Action',
    key: 'action',
    render: function(text, record, index){
      return (
        <span>
          <a><Icon type="plus" /></a>
          <span className="ant-divider" />
          <a><Icon type="close" /></a>
        </span>
      )
    }
  }
];
 
class UserIndex extends React.Component {
  constructor(props){
    super(props)
  }
 
  # 定义Context需要实现的方法
 
  getChildContext() {
    return {
      data: data,
      columns: columns
    };
  }
  render(){
    return (
      <Layout>
        <Sider>
          <div id="user-side-bar" className="side-bar">
          <Sidebar/>
          </div>
        </Sider>
        <Content>
          <h2 className="pagetitle">用户信息页</h2>
          <Row gutter={16}>
            <Col span={16}>
              <UserList />
            </Col>
            <Col span={4}>
              <Route path={`${this.props.match.url}/:id`} component={UserDetail}/>
            </Col>
          </Row>
        </Content>
      </Layout>
    )
  }
}
 
# 声明Context类型
 
UserIndex.childContextTypes = {
  data: PropTypes.array,
  columns: PropTypes.array,
};
 
export default UserIndex;

中间组件

中间中间不再通过组件属性一级一级的往下传递了. 我们这里在 render() 函数中定义一个空的 <List/>:

import { Table, Icon } from 'antd';
 
import {
  Link
} from 'react-router-dom';
 
import List from '../_common/List';
 
class UserList extends React.Component {
  constructor(props){
    super(props)
  }
  render(){
    return (
      <div>
        <List />
      </div>
    )
  }
}
 
export default UserList;

子组件, 列表

import React from 'react';
import PropTypes from 'prop-types';
import { Layout, Table } from 'antd';
const { Sider, Content } = Layout;
class List extends React.Component {
  constructor(props) {
    super(props);
  }
 
  render() {
    return (
      <Content>
        <Table columns={this.context.columns} dataSource={this.context.data} size="middle" />
      </Content>
    );
  }
}
 
List.propTypes = {
    data: PropTypes.array,
    columns: PropTypes.array
};
 
# 在这里声明 contextTypes 用于访问 UserIndex 组件中定义的Context数据.
 
List.contextTypes = {
  data: PropTypes.array,
  columns: PropTypes.array
};
 
export default List;

这样我们就可以在子组件中获取到父组件的数据了,不管多少层都能获取到。

猜你喜欢

转载自www.cnblogs.com/wind-wang/p/9857790.html