react-route簡單實現

調用界面

import React, {Component} from 'react';
// import {BrowserRouter, Link, Route, Switch} from "react-router-dom";
import {BrowserRouter, Link, Route} from "../../myReactRoute"; // 引入自己定義的文件
import UserPage from "./userPage";
import Home from "./Home";
class RouteCom extends Component {
    render() {
        return (
            <div>
                <h1>routeCom</h1>
                <BrowserRouter>
                        <Link to={'/'}>首頁</Link>
                        <Link to={'/user'}>用戶中心</Link>
                        <Link to={'/404'}>404</Link>

                        <Route exact path={'/'} component={Home}></Route>
                        <Route path={'/user'} component={UserPage}></Route>
                        <Route component={() => <h1>404</h1>} />

                </BrowserRouter>

            </div>
        );
    }
}

export default RouteCom;

自定義實現界面

import React, {Component, useContext} from 'react';
import {createBrowserHistory} from 'history' // 該包可以獲取當前路徑信息
const RouteContext = React.createContext() // 創建context傳值
const RouteProvider = RouteContext.Provider
const RouteConsumer = RouteContext.Consumer
export class BrowserRouter extends Component {
    constructor(props) {
        super(props);
        this.history = createBrowserHistory()
        console.log(this.history)
        this.state = {
            location: this.history.location //將路徑信息值傳遞給state以便進行雙向綁定
        }
        this.unlisten = this.history.listen((location) => {
            this.setState({
                location
            })
        })
        // console.log(this.history)
    }
    componentWillUnmount() {
        this.unlisten && this.unlisten() // 退出銷燬監聽
    }

    render() {
        const {children} = this.props
        const {location} = this.state
        return (
            // 將路徑信息值傳遞
            <RouteProvider value={{history: this.history, location: location}}>
                {children}
            </RouteProvider>
        );
    }
}
export  class Link extends Component { // link的本質還是一個a標籤
    handleClick = (event, ctx) => {
        event.preventDefault() // 屏蔽掉默認的a標籤的事件
        ctx.history.push(this.props.to) // 手動執行history事件
    }
    render() {
        const {children, to} = this.props
        return (
            <RouteConsumer>
                {
                   (ctx) => (
                    <a href={to} onClick={event => this.handleClick(event, ctx)}>
                    {children}
                    </a>
                    )
                }
            </RouteConsumer>

        );
    }
}
export  function Route (props){

    const ctx = useContext(RouteContext) // 因爲是函數組件,所以調用useContext拿到傳遞的值
    const {location} = ctx
    const {component, path} = props // props是該組件接受到的傳值參數
    const matchRoute = location.pathname === path // 頁面路徑和傳遞來的路徑相同則顯示對應組件
    return (
        matchRoute && component ? React.createElement(component) : null // 通過React.createElement可以將component渲染出來
    )
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章