国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

react-router-dom 的 HashRouter 也就這么回事兒

fnngj / 707人閱讀

摘要:要實現的功能我們使用開發項目的時候,基本上是單頁面應用,也就離不開路由。路由看似神秘,當我們簡單的模擬一下它的核心功能后,發現也就這么回事兒。實現的邏輯是,返回中跟匹配到的第一個孩子。

1 要實現的功能

我們使用React開發項目的時候,基本上是單頁面應用,也就離不開路由。路由看似神秘,當我們簡單的模擬一下它的核心功能后,發現也就這么回事兒。本文就詳細的介紹一下react-router-dom HashRouter的核心實現邏輯。

本文實現的功能主要包含:

HashRouter

Route

Link

MenuLink

Switch

Redirect

2 實現的邏輯

先不說代碼是怎樣寫的,先上圖,讓大家看一下這個HashRouter到底是個什么東東:

好吧,肯定有人會說這些圈圈又是什么東東呀,客官不要著急,待我慢慢解釋:

HashRouter是一個大的容器,它控制著他自己到底渲染成什么樣子,那么它是通過什么控制的呢,看它的名字就能猜出來,那就是window.location.hash

HashRouter開始渲染的時候就會拿它自己身上的pathname屬性跟它肚子里的Routepath進行匹配,匹配上的話,就會渲染Routecomponent對應的組件。

Link是怎樣切換路由的呢,很簡單,就是通過this.props.history.push(path)來改變HashRouter中的pathname屬性,進而驅動Route們 進行重新渲染,再次匹配我們的路由,最終實現路由的切換。

介紹了一下簡單的邏輯,接下來我們就看一下具體是怎樣實現的吧,如下圖:

HashRouter是一個繼承了React.Component的類,這個類上的state包括location,監聽著hash的變化以驅動Route組件的重新渲染,另外還有一個history屬性,可以切換頁面的路由。

本文要實現的功能中包括RouteLinkMenuLinkSwitchRedirect,其中Route的是基礎是核心,MenuLink和某些有特定邏輯的渲染都是在Route的基礎上實現的。

Route組件上可以接收三種變量,包括componentrenderchildren,其中renderchildren是都是函數,render是根據特定的邏輯渲染元素,children是用來渲染MenuLink,這兩個函數都接收當前路由的props,函數的返回值是要渲染的元素。

Switch實現的邏輯是,返回children中跟hash匹配到的第一個“孩子”。

3 具體的代碼邏輯 (1) HashRouter

HashRouterwindow.loacation.hash跟自己的state掛鉤,通過改變自己的state驅動頁面的重新渲染。

import React, {Component} from "react";
import PropTypes from "prop-types";

export default class HashRouter extends Component {
    constructor() {
        super();
        this.state = {
            location: {
                pathname: window.location.hash.slice(1) || "/", // 當前頁面的hash值
                state: {}   //保存的狀態
            }
        };
    }
    
    // 定義上下文的變量類型
    static childContextTypes = {
        location: PropTypes.object,
        history: PropTypes.object
    }
    
    // 定義上下文的變量
    getChildContext() {
        return {
            location: this.state.location,
            history: {
                push: (path) => { // 就是更新 window.hash值
                    if (typeof path === "object") {
                        let {pathname, state} = path;
                        this.setState({
                            location: {
                                ...this.state.location,
                                state // {from: "/profile"}
                            }
                        }, () => {
                            window.location.hash = pathname;
                        })
                    } else {
                        window.location.hash = path;
                    }
                }
            }
        }
    }
    
    render() {
        return this.props.children; // 渲染頁面元素
    }
    
    componentDidMount() {
        window.location.hash = window.location.hash.slice(1) || "/";
        // 監聽window的hash的變化,驅動頁面的重新刷新
        window.addEventListener("hashchange", () => {
            this.setState({
                location: {
                    ...this.state.location,
                    pathname: window.location.hash.slice(1) || "/"
                }
            });
        })
    }
}
(2) Route

Route的渲染核心邏輯就是將自己的path和當前頁面的hash進行匹配,匹配上了就渲染相應的元素,匹配不上就什么都不渲染。

import React, {Component} from "react";
import PropTypes from "prop-types";
import pathToRegexp from "path-to-regexp"

export default class Route extends Component {
    // 定義上下文context的類型
    static contextTypes = {
        location: PropTypes.object,
        history: PropTypes.object
    }
    
    render() {
        // 解構傳入Route的props
        let {path, component: Component, render, children} = this.props;
        
        // 解構上下文的屬性
        let {location, history} = this.context;
        let props = {
            location,
            history
        };
        
        // 將傳入Route的path和當前的hash進行匹配
        let keys = [];
        let regexp = pathToRegexp(path, keys, {end: false});
        keys = keys.map(key => key.name);
        
        let result = location.pathname.match(regexp);
        
        if (result) { // 匹配上了
            let [url, ...values] = result;
            props.match = {
                path,
                url,
                params: keys.reduce((memo, key, index) => { // 獲取匹配到的參數
                    memo[key] = values[index];
                    return memo;
                }, {})
            };
            
            if (Component) { // 普通的Route
                return ;
            } else if (render) { // 特定邏輯的渲染
                return render(props);
            } else if (children) { // MenuLink的渲染
                return children(props);
            } else {
                return null;
            }
        } else { // 沒有匹配上
            if (children) { // MenuLink的渲染
                return children(props);
            } else {
                return null;
            }
        }
    }
}
(3) Redirect

Redirect就干了一件事,就是改變HashRouterstate,驅動重新渲染。

import React, {Component} from "react";
import PropTypes from "prop-types";

export default class Redirect extends Component {
    // 定義上下文context的Type
    static contextTypes = {
        history: PropTypes.object
    }
    
    componentDidMount() {
        // 跳轉到目標路由
        this.context.history.push(this.props.to);
    }
    
    render() {
        return null;
    }
}
(4) MenuLink
import React, {Component} from "react";
import Route from "./Route";
import Link from "./Link"

export default ({to, children}) => {
    // 如果匹配到了,就給當前組件一個激活狀態的className
    return  (
        
  • {children}
  • ) }/> }
    (5) Link

    Link就是渲染成一個a標簽,然后給一個點擊事件,點擊的時候更改HashRouter的狀態,驅動重新渲染。

    import React, {Component} from "react";
    import PropTypes from "prop-types";
    
    export default class Link extends Component {
        static contextTypes = {
            history: PropTypes.object
        }
        
        render() {
            return (
                 this.context.history.push(this.props.to)}>{this.props.children}
            )
        }
    }
    (6) Switch
    import React, {Component} from "react";
    import PropTypes from "prop-types";
    import pathToRegexp from "path-to-regexp";
    
    export default class Switch extends Component {
        static contextTypes = {
            location: PropTypes.object
        }
        
        render() {
            let {pathname} = this.context.location;
            
            let children = this.props.children;
            for (let i = 0, l = children.length; i < l; i++) {
                let child = children[i];
                let path = child.props.path;
                
                if (pathToRegexp(path, [], {end: false}).test(pathname)) {
                    // 將匹配到的第一個元素返回
                    return child;
                }
            }
            return null
        }
    }
    4 寫在最后

    好了,這幾個功能介紹完了,你是否對HashRouter的原理有所了解了呢?本文只是貼出部分代碼,如果有需要請看demo可以手動體驗一下哦。

    參考文獻:

    react-router

    文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

    轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/94153.html

    相關文章

    • ReactRouter升級 v2 to v4

      摘要:概述相對于幾乎是重寫了新版的更偏向于組件化。汲取了很多思想,路由即是組件,使路由更具聲明式,且方便組合。如果你習慣使用,那么一定會很快上手新版的。被一分為三。不止是否有意義參考資料遷移到關注點官方文檔 概述 react-router V4 相對于react-router V2 or V3 幾乎是重寫了, 新版的react-router更偏向于組件化(everything is comp...

      JasonZhang 評論0 收藏0
    • react路由淺析

      摘要:瀏覽器端使用的和集成使用時會用到中路由分類基于提供的和事件來保持和的同步。路由剖析在上面的示例中是轉發的樞紐在這個中轉站有很多線路通過開關可以啟動列車的運行乘坐列車就可以發現新大陸。 引言 在使用react做復雜的spa開發中,開發中必不可少的就是react-router,它使用Lerna管理多個倉庫, 在browser端常使用的幾個如下所示 react-router 提供了路由的...

      jackzou 評論0 收藏0
    • 手挽手帶你學React:三檔 React-router4.x使用

      摘要:我們在內部來渲染不同的組件我們這里采用哈希路由的方式,鑒于的渲染機制,我們需要把值綁定進入內部。 手挽手帶你學React入門三檔,帶你學會使用Reacr-router4.x,開始創建屬于你的React項目 什么是React-router React Router 是一個基于 React 之上的強大路由庫,它可以讓你向應用中快速地添加視圖和數據流,同時保持頁面與 URL 間的同步。通俗一...

      SunZhaopeng 評論0 收藏0
    • [ 一起學React系列 -- 11 ] React-Router4 (1)

      摘要:中的包中的包主要有三個和。的理念上面提到的理念是一切皆組件以下統一稱組件。從這點來說的確方便了不少,也迎合一切皆組件的理念。組件是中主要的組成單位,可以認為是或的路由入口。將該標示為嚴格匹配路由。的屬性追加一條。 2019年不知不覺已經過去19天了,有沒有給自己做個總結?有沒有給明年做個計劃?當然筆者已經做好了明年的工作、學習計劃;同時也包括該系列博客剩下的博文計劃,目前還剩4篇:分別...

      tinysun1234 評論0 收藏0
    • react-router v5.x 源碼分析和理解 SPA router 原理

      摘要:一般情況下,都是作為等其他子路由的上層路由,使用了,接收一個屬性,傳遞給消費子組件。創建對象,兼容老瀏覽器,其他和沒有大區別總結分為四個包,分別為,其中是瀏覽器相關,是相關,是核心也是共同部分,是一些配置相關。 這篇文章主要講的是分析 react-router 源碼,版本是 v5.x,以及 SPA 路由實現的原理。 文章首發地址 單頁面應用都用到了路由 router,目前來看實現路由有...

      Harriet666 評論0 收藏0

    發表評論

    0條評論

    fnngj

    |高級講師

    TA的文章

    閱讀更多
    最新活動
    閱讀需要支付1元查看
    <