1. 程式人生 > >react-router的實現原理

react-router的實現原理

目前,react的生態越來越豐富,像flux redux react-router已經被越來越多的使用,本文就react-router的內部實現進行分析。文章主要包含兩大部分: 一是對react-router賴以依存的history進行研究;二是分析react-router是如何實現URLUI同步的。

1. react-router依賴基礎 - history

1.1 History整體介紹

history是一個獨立的第三方js庫,可以用來相容在不同瀏覽器、不同環境下對歷史記錄的管理,擁有統一的API。具體來說裡面的history分為三類:

  • 老瀏覽器的history: 主要通過hash來實現,對應createHashHistory

  • 高版本瀏覽器: 通過html5裡面的history,對應createBrowserHistory

  • node環境下: 主要儲存在memeory裡面,對應createMemoryHistory

上面針對不同的環境提供了三個API,但是三個API有一些共性的操作,將其抽象了一個公共的檔案createHistory:

// 內部的抽象實現
function createHistory(options={}) {
  ...
  return {
    listenBefore, // 內部的hook機制,可以在location發生變化前執行某些行為,AOP的實現
    listen, // location發生改變時觸發回撥
transitionTo, // 執行location的改變 push, // 改變location replace, go, goBack, goForward, createKey, // 建立location的key,用於唯一標示該location,是隨機生成的 createPath, createHref, createLocation, // 建立location } }

上述這些方式是history內部最基礎的方法,createHashHistorycreateBrowserHistorycreateMemoryHistory

只是覆蓋其中的某些方法而已。其中需要注意的是,此時的location跟瀏覽器原生的location是不相同的,最大的區別就在於裡面多了key欄位,history內部通過key來進行location的操作。

function createLocation() {
  return {
    pathname, // url的基本路徑
    search, // 查詢欄位
    hash, // url中的hash值
    state, // url對應的state欄位
    action, // 分為 push、replace、pop三種
    key // 生成方法為: Math.random().toString(36).substr(2, length)
  }
}

1.2 內部解析

三個API的大致的技術實現如下:

  • createBrowserHistory: 利用HTML5裡面的history

  • createHashHistory: 通過hash來儲存在不同狀態下的history資訊

  • createMemoryHistory: 在記憶體中進行歷史記錄的儲存

1.2.1 執行URL前進

  • createBrowserHistory: pushState、replaceState

  • createHashHistorylocation.hash=*** location.replace()

  • createMemoryHistory: 在記憶體中進行歷史記錄的儲存

虛擬碼實現如下:

// createBrowserHistory(HTML5)中的前進實現
function finishTransition(location) {
  ...
  const historyState = { key };
  ...
  if (location.action === 'PUSH') ) {
    window.history.pushState(historyState, null, path);
  } else {
    window.history.replaceState(historyState, null, path)
  }
}
// createHashHistory的內部實現
function finishTransition(location) {
  ...
  if (location.action === 'PUSH') ) {
    window.location.hash = path;
  } else {
    window.location.replace(
    window.location.pathname + window.location.search + '#' + path
  );
  }
}
// createMemoryHistory的內部實現
entries = [];
function finishTransition(location) {
  ...
  switch (location.action) {
    case 'PUSH':
      entries.push(location);
      break;
    case 'REPLACE':
      entries[current] = location;
      break;
  }
}

1.2.2 檢測URL回退

  • createBrowserHistorypopstate

  • createHashHistoryhashchange

  • createMemoryHistory: 因為是在記憶體中操作,跟瀏覽器沒有關係,不涉及UI層面的事情,所以可以直接進行歷史資訊的回退

虛擬碼實現如下:

// createBrowserHistory(HTML5)中的後退檢測
function startPopStateListener({ transitionTo }) {
  function popStateListener(event) {
    ...
    transitionTo( getCurrentLocation(event.state) );
  }
  addEventListener(window, 'popstate', popStateListener);
  ...
}

// createHashHistory的後退檢測
function startPopStateListener({ transitionTo }) {
  function hashChangeListener(event) {
    ...
    transitionTo( getCurrentLocation(event.state) );
  }
  addEventListener(window, 'hashchange', hashChangeListener);
  ...
}
// createMemoryHistory的內部實現
function go(n) {
  if (n) {
    ...
    current += n;
  const currentLocation = getCurrentLocation();
  // change action to POP
  history.transitionTo({ ...currentLocation, action: POP });
  }
}

1.2.3 state的儲存

為了維護state的狀態,將其儲存在sessionStorage裡面:

// createBrowserHistory/createHashHistory中state的儲存
function saveState(key, state) {
  ...
  window.sessionStorage.setItem(createKey(key), JSON.stringify(state));
}
function readState(key) {
  ...
  json = window.sessionStorage.getItem(createKey(key));
  return JSON.parse(json);
}
// createMemoryHistory僅僅在記憶體中,所以操作比較簡單
const storage = createStateStorage(entries); // storage = {entry.key: entry.state}

function saveState(key, state) {
  storage[key] = state
}
function readState(key) {
  return storage[key]
}

2. react-router的基本原理

一句話:實現URL與UI介面的同步。其中在react-router中,URL對應Location物件,而UI是由react components來決定的,這樣就轉變成locationcomponents之間的同步問題。

3. react-router具體實現

react-router在history庫的基礎上,實現了URL與UI的同步,分為兩個層次來描述具體的實現。

3.1 元件層面描述實現過程

react-router中最主要的componentRouter RouterContext Linkhistory庫起到了中間橋樑的作用。

3.2 API層面描述實現過程

為了簡單說明,只描述使用browserHistory的實現,hashHistory的實現過程是類似的,就不在說明。

4. 結語

目前react-router在專案中已有大量實踐,其優點可以總結如下:

  • 風格: 與React融為一體,專為react量身打造,編碼風格與react保持一致,例如路由的配置可以通過component來實現

  • 簡單: 不需要手工維護路由state,使程式碼變得簡單

  • 強大: 強大的路由管理機制,體現在如下方面

    • 路由配置: 可以通過元件、配置物件來進行路由的配置

    • 路由切換: 可以通過<Link> Redirect進行路由的切換

    • 路由載入: 可以同步記載,也可以非同步載入,這樣就可以實現按需載入

  • 使用方式: 不僅可以在瀏覽器端的使用,而且可以在伺服器端的使用

當然react-router的缺點就是API不太穩定,在升級版本的時候需要進行程式碼變動。

相關推薦

react-router實現原理

react-router實現原理獲取html文件#後面的部分: window.location.hash 添加onhashchange事件,監聽路由變化: window.onhashchange = function(){ } 完整代碼: <a href="#/home">home</a&g

深入解析React Event實現原理

React 元素的事件處理和 DOM元素的很相似。但是有一點語法上的不同: React事件繫結屬性的命名採用駝峰式寫法,而不是小寫。 如果採用 JSX 的語法你需要傳入一個函式作為事件處理函式,而不是一個字串(DOM元素的寫法) 並且 React 自己內部實現了一

初探React-router實現導航

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

react native 實現原理解析

建立HelloWord工程 熟悉完環境的搭建,按照慣例,我們來建立一個HelloWord工程,用來分析RN的實現原理。 廢話不多說,show the code 首先開啟終端,輸入 react-native init YourProjectName

深入理解react-router 路由的實現原理

React Router 是一個基於 React 之上的強大路由庫,它可以讓你嚮應用中快速地新增檢視和資料流,同時保持頁面與 URL 間的同步。本文從兩個方便來解析 react-router 實現原理。一:介紹 react-router 的依賴庫history;二:使用 history 庫,實現一個簡單的 r

react-router實現原理

目前,react的生態越來越豐富,像flux redux react-router已經被越來越多的使用,本文就react-router的內部實現進行分析。文章主要包含兩大部分: 一是對react-router賴以依存的history進行研究;二是分析react-router是

react-router-dom實現全局路由登陸攔截

狀態 統一管理 hist pan erro extend urn app.js cati   相比與vue的路由集中式管理,能夠很好的進行統一的路由操作,react的路由看起來更亂,想要進行像vue的全局路由管理不是那麽得心應手。在我們的項目中,有很多頁面是需要登陸權限驗證

vue-router的簡單實現原理

lan type script min cal ont document .ajax scale <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF

React-router、antd實現同步瀏覽器地址高亮對應選單

關於 React 和 antd 元件庫 React 是目前主流的前端開發框架,目前前端流行的框架是 Angular,Vue,React,具體選型看專案需求而定。 antd 是基於 React 開發的元件庫,有螞蟻金服團隊退出,目前使用人數較多,元件也比較多,文件也很友好。 本次我做的就是使用 antd

React+React Router+React-Transition-Group實現頁面左右滑動+滾動位置記憶

在React Router中,想要做基於路由的左右滑動,我們首先得搞清楚當發生路由跳轉的時候到底發生了什麼,和路由動畫的原理。   首先我們要先了解一個概念:history。history原本是內置於瀏覽器內的一個物件,包含了一些關於歷史記錄的一些資訊,但本文要說的history是React-R

示例React-router 路由切換動畫的實現

因為專案的需求,需要在路由切換的時候,加入一些比較 zb 的視覺效果,所以研究了一下。把這些學習的過程記錄下來,以便以後回顧。同時也希望這些內容能夠幫助一些跟我一樣的菜鳥,讓他們少走些坑。可能我對程式碼的表述不是很到位,希望大家不要介意。機智的你們一定可以看明白。 1.外掛依賴 使用的外掛是react-tr

從路由原理出發,深入閱讀理解react-router 4.0的原始碼

  react-router等前端路由的原理大致相同,可以實現無重新整理的條件下切換顯示不同的頁面。路由的本質就是頁面的URL發生改變時,頁面的顯示結果可以根據URL的變化而變化,但是頁面不會重新整理。通過前端路由可以實現單頁(SPA)應用,本文首先從前端路由的原

react用起來更得心應手——(react-router原理簡析)

讓react用起來更得心應手系列文章: 前端路由和後臺路由 在剛入行的時候一直明白什麼單頁面應用是什麼,說白了就是混淆了前臺路由和後臺路由,現在來縷縷它們: 前臺路由:頁面的顯示由前臺js控制,在url的路徑中輸入雜湊值是不會往後臺傳送請求的,所以前臺可以通過將雜湊和頁

Router原理React-Router

Router原理和React-Router 1 Rouer原理 Router指的是瀏覽器中一種處理訪問先後關係的機制,簡單點來說就是允許我們在不同頁面進行跳轉然後記錄跳轉關係還能原路退回的機制。 三個要素: 歷史:棧的形式 跳轉:負責不同頁面的挑戰動作,並且

實現react-router v4(上)

寫在前面 用react-router v4可以實現單頁面應用,可以將元件對映到路由上,將對應的元件渲染到想要渲染的位置。 react路由有兩種方式:一種是HashRouter,即利用hash實現路由切換。另一種是BrowserRouter,即利用html5 API實現路由的切換。本文是在閱讀react-ro

vue-router的使用及實現原理

前端路由是直接找到與地址匹配的一個元件或物件並將其渲染出來。改變瀏覽器地址而不向伺服器發出請求有兩種方式: 1. 在地址中加入#以欺騙瀏覽器,地址的改變是由於正在進行頁內導航 2. 使用H5的window.history功能,使用URL的Hash來模擬一個完

react-router原理

在一個web應用中,路由系統是不可或缺的一部分。許多前端框架都會有著不同的配套的路由系統,最近也開始接觸react,瞭解了一點react-router的實現原理。 hash路由 早期的前端路由是通過hash來實現的。改變url的hash值並不會重新整理頁面,因此

vue資料雙向繫結的原理和vue-router路由的實現原理

vue實現雙向資料繫結的原理就是利用了 Object.defineProperty() 這個方法重新定義了物件獲取屬性值(get)和設定屬性值(set)的操作來實現的。 在MDN上對該方法的說明是:Object.defineProperty() 方法會直接在一個物件上定義一

前端路由實現react-router 原始碼分析

在單頁應用上,前端路由並不陌生。很多前端框架也會有獨立開發或推薦配套使用的路由系統。那麼,當我們在談前端路由的時候,還可以談些什麼?本文將簡要分析並實現一個的前端路由,並對 react-router 進行分析。 一個極簡前端路由實現 說一下前端路由實現的簡要原理,以 hash

react通過react-router-dom攔截實現登入驗證

在使用react開發專案中,有些頁面需要登入之後才能訪問,所以需要進行攔截,此處分享採用react-router-dom v4+redux+redux-saga+ant-mobile+axios技術來實現 Login.jsx import React from "reac