摘要:新增一條記錄替換當前的記錄實現核心路由綁定標簽綁定事件并阻止默認事件總結本文只是簡述了,路由變化原理,并未去結合去完成實現一個框架路由。
前言
最近學習react時,在使用react-router-dom的時候,對history原理與路由切換實現并不了解,經過學習后總結一下吧!
如果你只是使用react 自帶history 那下面這些原理,你可能并不會用到。但當需要使用自己的history 或 使用第三方history 的時候你就需要了解其原理
在react 中,你要在非組件內可以靈活的切換路由,那么你就要使用自定義的history。
// app.jsx import React from "react" import "./App.scss" import { BrowserRouter } from "react-router-dom" import history from "./history" import XtContent from "./layout/content" import Login from "./components/loginModal" function App() { return (模式) } export default App // history.js // 這里使用第三方創建history import { createBrowserHistory } from "history" export default createBrowserHistory() // 在封裝的fetch中使用 import axios from "axios" import history from "@/history"; // 設置axios 通用 const service = axios.create({ timeout: 5000, headers: { "Content-Type": "application/json;charset=UTF-8" }, withCredentials: true }) // 響應攔截 service.interceptors.response.use( response => { //服務端定義的響應code碼為0時請求成功 if (response.data.code === 200) { //使用Promise.resolve 正常響應 return Promise.resolve(response.data) } else if (response.data.code === 1002) { //服務端定義的響應code碼為1401時為未登錄 message.error("登陸失效,請從新登陸!") /////////// 登陸失敗切換登陸頁面 **history.push("/Login")** ////////// window.localStorage.removeItem("userInfo") return Promise.reject(response.data) //使用Promise.reject 拋出錯誤和異常 } else { message.error(response.data.message) return Promise.reject(response.data) } }, error => { if (error && error.response) { let res = {} res.code = error.response.status res.msg = throwErr(error.response.status, error.response) //throwErr 捕捉服務端的http狀態碼 定義在utils工具類的方法 message.error(res.msg) return Promise.reject(res) } return Promise.reject(error) } )
在React/Vue的路由時,會有兩種模式 hash 和 history ,事實上他們是針對游覽器的路由模式設置的。其基本原理實際就是通關游覽器提供的監聽這兩種模式的變化,從而映射的對應路由的組件render.
基與以上理論簡單實現一下路由切換 hashhash 其兼容性好,但一般不采用只是在不支持H5 history 的情況下回退到hash。其在游覽器上的路由形式 http://localhost#/test 與正常路由相比略顯怪異且不美觀(不推薦使用)
核心:監聽hash變化觸發callback // window.addEventListener("hashchange", callback)
// 模擬實現 class Router { constructor() { // 儲存 hash 與 callBack 的映射 this.routes = {}; // 當前 路由 this.currentUrl = ""; // 存儲歷史記錄 this.history = []; // 作為指針,默認指向 this.history 的末尾,根據后退前進指向 history 中不同的 hash this.currentIndex = this.history.length - 1; this.backIndex = this.history.length - 1 this.refresh = this.refresh.bind(this); this.backOff = this.backOff.bind(this); // 默認不是后退操作 this.isBack = false; // 監聽load后加載路由 window.addEventListener("load", this.refresh, false); // 監聽hash 變化 //window.addEventListener("hashchange", this.refresh, false); } //路由實例 加添路由映射 route(path, callback) { this.routes[path] = callback || function() {}; } // 根據由render refresh() { console.log("refresh") this.currentUrl = location.hash.slice(1) || "/"; this.history.push(this.currentUrl); this.currentIndex++; if (!this.isBack) { this.backIndex = this.currentIndex } this.routes[this.currentUrl](); console.log("指針:", this.currentIndex, "history:", this.history); this.isBack = false; } // 后退功能 backOff() { // 后退操作設置為true console.log(this.currentIndex) console.log(this.backIndex) this.isBack = true; this.backIndex <= 0 ? (this.backIndex = 0) : (this.backIndex = this.backIndex - 1); location.hash = `#${this.history[this.backIndex]}`; } } // 調用 window.router = new Router() router.route("/", function () { console.log("") changeContent("") }) router.route("/Home1", function () { console.log("Home1") changeContent("Home1") }) router.route("/Home2", function () { console.log("Home2") changeContent("Home2") }) router.route("/Home3", function () { console.log("Home3") changeContent("Home3") })history history API (pushState replaceState)
將游覽器地址上路由切換
修改歷史記錄
不會刷新頁面
其路由形式為游覽器標準,所以當切換到某一路由localhost/test 后再刷新游覽器(F5),游覽器會向服務器請求/test下對應的資源,然鵝路由是在前端實現的服務器會找不到資源,在這種模式需要將服務器接收到的get(contentType = text/html)請求統一返回index.html。下面已node-koa為例
const Koa = require("koa") // 一個處理前端路由hisrtory模式的node插件 const history = require("koa2-connect-history-api-fallback") const app = new Koa() // 將contentType 為 text/html, application/xhtml+xml 統一返回靜態資源文件下的index.html app.use(history({ htmlAcceptHeaders: ["text/html", "application/xhtml+xml"] })) * koa2-connect-history-api-fallback 見 https://github.com/davezuko/koa-connect-history-api-fallback
/** * state :歷史記錄相關聯的狀態對象,當popstate事件觸發時,會把該對象傳入回調函數。不用可傳null。 * title: 新頁面的標題不用可傳null。 * url: 要切換到的路徑,必須保持與當前URL同一個域。 **/ // 新增一條記錄 history.pushState(state, title, url) // 替換當前的記錄 history.replaceState(state, title, url)
#### 實現 #####
* 核心 window.addEventListener("popstate",callBack) class Routers { constructor() { this.routes = {}; this._bindPopState(); } init(path) { history.replaceState({path: path}, null, path); this.routes[path] && this.routes[path](); } route(path, callback) { this.routes[path] = callback || function() {}; } go(path) { history.pushState({path: path}, null, path); this.routes[path] && this.routes[path](); } _bindPopState() { window.addEventListener("popstate", e => { const path = e.state && e.state.path; this.routes[path] && this.routes[path](); }); } } window.Router = new Routers(); Router.init(location.pathname); // 路由綁定 Router.route("/", function() { console.log("/") }); Router.route("/blue", function() { console("blue"); }); Router.route("/green", function() { console("green"); }); // a標簽綁定事件、并阻止默認事件 a.addEventListener("click", e => { if (e.target.tagName === "A") { e.preventDefault(); Router.go(e.target.getAttribute("href")); } });總結
本文只是簡述了,路由變化原理,并未去React/Vue結合 去完成實現一個框架路由。后續學習后會補上!
參考Hash路由
history路由
作者:易企秀——D_Q_
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106516.html
摘要:新增一條記錄替換當前的記錄實現核心路由綁定標簽綁定事件并阻止默認事件總結本文只是簡述了,路由變化原理,并未去結合去完成實現一個框架路由。 前言 最近學習react時,在使用react-router-dom的時候,對history原理與路由切換實現并不了解,經過學習后總結一下吧! 如果你只是使用react 自帶history 那下面這些原理,你可能并不會用到。但當需要使用自己的hist...
摘要:我們知道是的核心插件,而當前項目一般都是單頁面應用,也就是說是應用在單頁面應用中的。原理是傳統的頁面應用,是用一些超鏈接來實現頁面切換和跳轉的其實剛才單頁面應用跳轉原理即實現原理實現原理原理核心就是更新視圖但不重新請求頁面。 近期面試,遇到關于vue-router實現原理的問題,在查閱了相關資料后,根據自己理解,來記錄下。我們知道vue-router是vue的核心插件,而當前vue項目...
摘要:顯示為顯示為顯示為單頁面應用用戶訪問軌跡埋點開發過單頁面應用的同學,一定比較清楚,單頁面應用的路由切換是無感知的,不會重新進行請求去獲取頁面,而是通過改變頁面渲染視圖來實現。 前言 最近開發的埋點項目,需要記錄用戶行為軌跡即用戶頁面訪問順序。需要在頁面跳轉的時候,記錄用戶訪問的信息(比如 url ,請求頭部等),非單頁面應用可以給 window 對象加上一個 beforeunload ...
摘要:而路由則是使用了中新增的事件和事件。總結這一章主要是介紹了如何使用在中構建我們的前端路由。 系列目錄地址 一、基礎知識概覽 第一章 - 一些基礎概念(posted at 2018-10-31) 第二章 - 常見的指令的使用(posted at 2018-11-01) 第三章 - 事件修飾符的使用(posted at 2018-11-02) 第四章 - 頁面元素樣式的設定(posted a...
閱讀 3579·2021-11-04 16:06
閱讀 3573·2021-09-09 11:56
閱讀 842·2021-09-01 11:39
閱讀 893·2019-08-29 15:28
閱讀 2289·2019-08-29 15:18
閱讀 823·2019-08-29 13:26
閱讀 3327·2019-08-29 13:22
閱讀 1039·2019-08-29 12:18