通过componentWillReceiveProps()实现React左右父子页面的联动效果

1.实现效果:

  • 通过单击左侧导航栏(父页面)内容,右侧(子页面)内容联动(呈现对应的导航栏内容),具体页面效果如下
  • 单击“几何图形初步”,右侧子页面显示“几何图形初步”

  • 单击"定义",右侧子页面显示"定义"

2.父页面Slider.js:单击具体列表导航栏抛出对应contentInformation redux,(通过react的antd组件库中的Tree组件实现列表导航栏效果),代码如下

  • 需要通过import { Tree } from 'antd'引入使用;
  • 定义:const TreeNode = Tree.TreeNode;
import React, { Component } from 'react';
import { Router, Route, hashHistory, IndexRoute, Redirect, IndexLink } from 'react-router';
import { Link, HashRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import 'antd/dist/antd.css';  // Add
import { Layout, Menu, Breadcrumb, Icon, Tree, Button, Radio, Row, Col, Modal } from 'antd';
const { Header, Content, Footer, Sider } = Layout;
const TreeNode = Tree.TreeNode;
class Slider extends Component {
    // 状态机
    constructor(props, context) {
        super(props, context);
        this.state = {
	//列表导航栏数据
            treeData: [
                {
                    "title": "几何图形初步",
                    "isLeaf": false
                },
                {                    
                    "title": "一元一次方程",                    
                    "isLeaf": false
                },
                {
                    "title": "整式",
                    "isLeaf": false
                },
                {                 
                    "title": "有理数",                 
                    "isLeaf": false
                }
            ],
        }
    }
    onLoadData = (treeNode) => {
        return new Promise((resolve) => {
            if (treeNode.props.children) {
                resolve();
                return;
            }
            setTimeout(() => {
                treeNode.props.dataRef.children = [
                    { title: '定义' ,isLeaf: false },
                    { title: '概念' ,isLeaf: false  },
                ];
                this.setState({
                    treeData: [...this.state.treeData],
                });
                resolve();
            }, 1000);
        });
    }
    renderTreeNodes(data) {
        return data.map((item) => {
            if (item.children) {
                return (
                    <TreeNode title={<p onClick={this.handleClick.bind(this, item.title)}>{item.title}</p>} key={item.key} dataRef={item}>
                        {this.renderTreeNodes(item.children)}
                    </TreeNode>
                );
            }
            return <TreeNode {...item} title={<p onClick={this.handleClick.bind(this, item.title)}>{item.title}</p>} dataRef={item} />;
        });
    }
    // 左侧导航栏单击事件,抛出redux即导航栏内容,供子页面接收
    handleClick(title) {
        console.log('左侧导航栏-单击事件')   
        const { contentInformation } = this.props;
        contentInformation ({
            type: 'contentInformation ',
            payload: { content_title: title },
        });
    }
    render() {
        return (
            <Layout>
                <Layout style={{ padding: '10px 0', background: '#fff' }}>
                    <Sider style={{ background: '#fff', paddingLeft: '15px', paddingTop: '30px', width: '300px' }}>
                        <Tree loadData={this.onLoadData.bind(this)} defaultSelectedKeys='0' >
                            {this.renderTreeNodes(this.state.treeData)}
                        </Tree>
                    </Sider>
                    <Content style={{ padding: '0 24px', minHeight: 280 }}>
                        {this.props.children}     //加载子页面所在位置
                    </Content>
                </Layout>
            </Layout>
        );
    }
}
function mapStateToProps(state) {
    return {
    };
}
function mapDispatchToProps(dispatch) {
    return {
        contentInformation : (state) => dispatch(state), //抛出redux
    };
}
export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Slider);

3.子页面Detail.js:接收父页面传来的contentInformation redux,首次通过componentDidMount接收,非首次通过componentWillReceiveProps(nextProps)接收,代码如下

import React, { Component } from 'react';
import { Router, Route, hashHistory, IndexRoute, Redirect, IndexLink } from 'react-router';
import { Link, HashRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import 'antd/dist/antd.css';  // Add
import { Card } from 'antd';
class Detail extends React.Component {
  // 状态机
  constructor(props, context) {
    super(props, context);
    this.state = {
      content: null,
    }
  }
//首次接收加载此周期函数
  componentDidMount() {  
    const { contentInformation } = this.props;
    const content_title= contentInformation.content_title;
    this.setState({ content: content_title});
  }
//非首次接收加载此周期函数,如果不使用此周期函数接收,子页面只能成功接收一次redux取值,因为componentDidMount不再重新加载,不了解此周期函数的使用,进一步学习可参考:http://blog.csdn.net/zrcj0706/article/details/78608740
  componentWillReceiveProps(nextProps) { 
    console.log("打印nextProps")
    console.log(nextProps)
    console.log(nextProps.contentInformation.content_title)
    this.setState({ content: nextProps.contentInformation.content_title});
  }
  render() {
    return (
      <div>
        <div style={{ paddingTop: '100px' }}>
          <div >
            <Card style={{ background: '#9ccc65' }}>
              {this.state.content}
            </Card>
          </div>
        </div>
      </div >
    );
  }
}
function mapStateToProps(state) {
  return {
    contentInformation: state.reducer_content.content.InformationInformation  //接收redux
  };
}
function mapDispatchToProps(dispatch) {
  return {
  };
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Detail);

4.通过react-router 4.2.0设置父子页面的路由关系

import React, { Component } from 'react';
import { Router, Route } from 'react-router';
import { Link, HashRouter } from 'react-router-dom';
import Slider from '../components/Slider.js';//左侧导航栏(父)页面
import Detail from '../components/Detail.js';//右侧内容(子)页面
export default class Routerindex extends Component {
    render() {
        return (
            <Slider path="/Slider " component={Slider }>
                <Route exact path='/Slider/Detail' component={Detail} />               
            </Slider >
        )
    }
}

5.设置redux

import { combineReducers } from 'redux'   //必须导入
function reducer_content(state = {}, action) {
    switch (action.type) {
        case 'contentInformation':
            console.log("contentInformation");
            console.log(action.payload);
            return { contentInformation: action.payload };
        default:
            return state;
    }
}

6.特别说明

 
  
  • componentWillReceiveProps使用时要加上nextProps参数,此函数通过该参数接收内容,不了解的可先打印后使用
  • 区别于componentDidMount函数的使用,正确使用
componentWillReceiveProps(nextProps) { 
    console.log("打印nextProps")
    console.log(nextProps)
    console.log(nextProps.contentInformation.content_title)
    this.setState({ content: nextProps.contentInformation.content_title});
  }
  • 而非如下使用
componentWillReceiveProps(nextProps) { 
    const { contentInformation } = this.props;
    const content_title= contentInformation.content_title;
    this.setState({ content: content_title});
  }








猜你喜欢

转载自blog.csdn.net/zrcj0706/article/details/78637353
今日推荐