天天看點

【React+Typescript+Antd】頁面内局部路由跳轉

一般地,首頁需要在全局路由的基礎上,增加頁面路由功能。

因為首頁有導航,有頁頭、頁尾這些固定的布局,而内容闆塊可以随導航而變動。這時候全局路由已經不能滿足頁面局部重新整理的需求。

假設首頁架構頁面是一個獨立元件,并稱為父元件,Content内容由各導航所對應的頁面元件按需替換加載。則頁面内跳轉有如下情況。

1、父元件跳轉子元件;

2、子元件跳轉兄弟元件;

父元件跳轉子元件

這個實作簡單,隻要在父元件的Content區域,用子元件替換即可。

  1. 父元件代碼:
contentView = () => {
        switch (this.state.infoType) {
            case 'dashboard':
                console.log('Dashboard')
                return <MainPage jumpFunc={this.jumpFunc} />

            case 'team':
                console.log('TeamConfig')
                return <TeamConfig />

            case 'project':
                console.log('ProjectList')
                return <ProjectList jumpFunc={this.jumpFunc} />

            case 'projectDetail':
                console.log('ProjectDetail')
                return <ProjectDetail jumpFunc={this.jumpFunc} params={this.state.params} />

            case 'codeReview':
                console.log('Code Review')
                return <CodeReview />

            case 'base':
                return <MyInfo userid='666' infoType='base' />

            case 'sec':
                return <MyInfo userid='666' infoType='sec' />
            default:
                break;
        }
        return <MyInfo userid='666' infoType='sec' />
    }

 render() {
        return (
            <Layout>
                <Sider
                    width='250'
                    trigger={null}
                    collapsible
                    collapsed={this.state.collapsed}>
                    <div className='naviHeader'>
                        <img src={logo} className="headerLogo" />
                    </div>
                    <Menu
                        defaultSelectedKeys={['1']}
                        defaultOpenKeys={['sub1']}
                        mode="inline"
                        theme="dark"
                        inlineCollapsed={this.state.collapsed}
                        onSelect={this.tabSelect}
                    >
                        <Menu.Item key="dashboard" className='naviCell'>
                            <Icon type="dashboard" style={{ fontSize: 20 }} />
                            <span className='naviItemTitle'>Dashboard</span>
                        </Menu.Item>
                        <Menu.Item key="project" className='naviCell'>
                            <Icon type="code" style={{ fontSize: 20 }} />
                            <span className='naviItemTitle'>Project</span>
                        </Menu.Item>
                        <Menu.Item key="codeReview" className='naviCell'>
                            <Icon type="code" style={{ fontSize: 20 }} />
                            <span className='naviItemTitle'>Code Review</span>
                        </Menu.Item>
                        <Menu.Item key="tool" className='naviCell'>
                            <Icon type="tool" style={{ fontSize: 20 }} />
                            <span className='naviItemTitle'>Dev Tools</span>
                        </Menu.Item>
                        <Menu.Item key="team" className='naviCell'>
                            <Icon type="team" style={{ fontSize: 20 }} />
                            <span className='naviItemTitle'>Team Config</span>
                        </Menu.Item>
                    </Menu>
                </Sider>
                <Layout>
                    <Header style={{ background: '#fff', padding: 0 }} className='myInfoHeader'>
                        <Icon
                            className="trigger"
                            type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
                            style={{ paddingLeft: 20 }}
                            onClick={this.toggle}
                        />
                        <div className='myInfo'>
                            <Dropdown overlay={this.menu}>
                                <a className="ant-dropdown-link myInfoEntrance" href="#">
                                    <Icon type="user" />
                                    <div style={{ paddingLeft: 10 }}>朱老闆</div>
                                </a>
                            </Dropdown>
                        </div>
                    </Header>
                    <Content
                        style={{
                            minHeight: 800,
                        }}
                    >
                        {this.contentView()}
                    </Content>
                </Layout>
            </Layout>
        );
    }           

複制

父元件是通過Layout布局進行整體架構,Sider控制Content顯示的内容。

contentView方法裡面通過判斷key值進行不同子元件的展示。

兄弟元件直接互相跳轉。

父元件跳轉子元件容易,那子元件如何跳轉到其他子元件呢?

如果通過全局路由,必定會引起頁面整體重新整理,不利益體驗。

如何自定義局部路由?

這就是問題的關鍵。

其實需要用到狀态提升(或者說共用狀态)

跳轉步驟如下:

  1. 在父元件中定義跳轉方法,并可以傳入參數(包括跳轉的頁面,以及頁面所需參數),并将方法綁定到全局狀态;
  2. 子元件中定義跳轉方法,并将方法綁定到全局狀态;
  3. 在子元件跳轉方法中擷取父元件方法并傳入需要跳轉的兄弟元件參數進行調用;

1、定義父元件跳轉方法

class ARLayout extends React.Component {
    constructor(props: any) {
        super(props)
        this.jumpFunc = this.jumpFunc.bind(this);

    }
    state = {
        collapsed: false,
        contentView: <MyInfo userid='666' infoType='base' />,
        infoType: 'base',
        params: '',
    };


    jumpFunc(type: any, param: any) {
        this.setState({
            infoType: type,
            params: param,
        });
    }
    contentView = () => {
        switch (this.state.infoType) {
            case 'dashboard':
                console.log('Dashboard')
                return <MainPage jumpFunc={this.jumpFunc} />

            case 'team':
                console.log('TeamConfig')
                return <TeamConfig />

            case 'project':
                console.log('ProjectList')
                return <ProjectList jumpFunc={this.jumpFunc} />

            case 'projectDetail':
                console.log('ProjectDetail')
                return <ProjectDetail jumpFunc={this.jumpFunc} params={this.state.params} />

            case 'codeReview':
                console.log('Code Review')
                return <CodeReview />

            default:
                break;
        }
        return <MyInfo userid='666' infoType='sec' />
    }


 ……
}           

複制

關鍵代碼1、需在構造方法裡面綁定this,這樣就可以在其他頁面通路到jumpFunc方法;

constructor(props: any) {
        super(props)
        this.jumpFunc = this.jumpFunc.bind(this);

    }           

複制

關鍵代碼2、在跳轉代碼裡重新整理參數,重新整理之後會重新更新布局。

jumpFunc(type: any, param: any) {
        this.setState({
            infoType: type,
            params: param,
        });
    }           

複制

2、定義跳轉的子元件

class ProjectList extends React.Component<any> {
    constructor(props: any) {
        super(props);
        this.showDetail = this.showDetail.bind(this);
    }

    showDetail(item: any) {
        this.props.jumpFunc("projectDetail", item);
        console.log("projectName:" + item.projectName);
    };
}           

複制

關鍵代碼1、在構造方法裡給跳轉方法綁定this;

關鍵代碼2、在跳轉方法裡擷取父元件的跳轉方法,并調用;

關鍵代碼3、因為構造方法入參是any類型,所有類的繼承也要加上any(

React.Component<any>

);

3、被跳轉的子元件,接收跳轉參數

import React from "react";
import "./ProjectDetail.css";
import ProjectDetailHeader from "./ProjectDetailHeader";
import ProjectDetailPanelLint from "./ProjectDetailPanelLint";
import { Layout, Row, Col } from "antd";
import ProjectDetailPanelAutoTest from "./ProjectDetailPanelAutoTest";
import ProjectDetailPanelCICD from "./ProjectDetailPanelCICD";
const { Header, Content, Footer, Sider } = Layout;

class ProjectDetail extends React.Component<any> {

    render() {
        return (
            <Layout className="pd-body">
                <Header className="pd-header" style={{ background: '#fff', padding: 0, height: 240 }}>
                    <ProjectDetailHeader jumpFunc={this.props.jumpFunc} params={this.props.params} />
                </Header>
                <Content style={{ background: 'none', padding: 0, margin: 24 }}>
                    <div className="pd-content">
                        <Row>
                            <Col span="24">
                                <div className="pd-panel">
                                    <ProjectDetailPanelCICD />
                                </div>
                                <div className="pd-panel">
                                    <ProjectDetailPanelLint />
                                </div>
                                <div className="pd-panel">
                                    <ProjectDetailPanelAutoTest />
                                </div>
                            </Col>
                        </Row>
                    </div>
                </Content>
            </Layout>
        );
    }
}

export default ProjectDetail;           

複制

上面代碼接收參數之後又直接透傳給了子元件:

<ProjectDetailHeader jumpFunc={this.props.jumpFunc} params={this.props.params} />           

複制

子元件也通過同樣的方式(

this.props.params

)擷取參數,然後展示。

以上就是局部跳轉的全部内容,歡迎留言交流。