跪拜 Guibai
← All articles
JavaScript

SPA Routing from Scratch: Why the Hash Fragment Powers Every Single-Page App

By 嘟嘟0717 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Understanding the hash-based mechanism strips away the magic from libraries like React Router and Vue Router. When a developer knows that a `<Link>` is just an `<a>` tag with a `#` and a `hashchange` listener, debugging routing bugs and evaluating framework choices becomes a matter of engineering rather than faith.

Summary

Traditional multi-page websites reload the entire DOM on every navigation, causing a visible white flash. Single-page applications eliminate this by loading a shell once and swapping content dynamically inside a mount point. The mechanism that makes this possible is the URL hash fragment—the part after the `#` symbol—which can be changed freely without triggering an HTTP request. A hand-written HashRouter class demonstrates the core logic: a routing table stored as a plain JavaScript object, a `hashchange` event listener, and a `load` method that matches the current hash to a callback and updates the DOM. The `bind(this)` pattern is essential to keep the event handler's context pointing to the router instance rather than the `window` object. This same pattern underpins every major front-end routing library, including React Router.

Takeaways
Changing any part of a URL except the hash fragment forces the browser to send a new HTTP request and reload the page.
The `hashchange` event fires automatically whenever the part of the URL after `#` changes, providing a hook for JavaScript to react without polling.
A front-end routing table is just a plain object where keys are hash paths and values are callback functions that update the DOM.
Using `bind(this)` in an event listener locks the callback's context to the class instance, preventing `this` from being reassigned to the `window` object.
React Router's `<Link>` component is an abstraction over an `<a>` tag with a `#` href, and `<Route>` is a declarative wrapper around a routing table lookup.
Conclusions

The creative leap of SPA routing is repurposing a browser feature designed for in-page anchor navigation to simulate full page transitions. The browser thinks it is scrolling to a bookmark, but the application treats it as a route change.

Frameworks add considerable weight to a concept that can be implemented in roughly 30 lines of vanilla JavaScript. The hand-written version exposes how thin the abstraction really is, which makes framework overhead easier to quantify.

The `bind(this)` problem in event handlers is a recurring source of bugs that persists even in modern frameworks under the hood; seeing it in a minimal router makes the pattern recognizable across codebases.

Concepts & terms
SPA (Single Page Application)
A web application that loads a single HTML page and dynamically updates content using JavaScript, avoiding full-page reloads during navigation.
URL Hash Fragment
The portion of a URL following the `#` symbol. Browsers do not send this fragment to the server, making it safe to change without triggering a network request.
hashchange Event
A native browser event that fires whenever the hash fragment of the current URL changes, providing the notification mechanism for hash-based routers.
Routing Table
In a front-end context, a data structure (typically a plain object) that maps URL paths to handler functions responsible for rendering the corresponding view.
Mount Point
A designated DOM element, often an empty `<div>`, that serves as the container where a JavaScript framework or router injects and swaps page content.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗