跪拜 Guibai
← All articles
Frontend

The 60-Line Hash Router That Explains Every Modern Front-End Framework

By 喜欢睡觉 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Modern frameworks abstract routing behind declarative APIs, but the underlying mechanism — a lookup table, a URL-change event, and a DOM swap — has not changed. Knowing the 60-line core prevents treating React Router or Vue Router as magic and makes debugging route transitions, `this`-binding bugs, and lazy-loading splits far more straightforward.

Summary

Traditional multi-page applications reload the entire document on every navigation, causing white flashes, redundant bandwidth consumption, and total state loss. The pivot to single-page applications began when developers realized that hash fragments — originally meant for in-page anchor links — never trigger a page refresh, making them a natural vehicle for client-side routing. A minimal HashRouter class, built with a routing table object, a `hashchange` event listener, and a `load()` dispatcher, replaces only the target DOM region while keeping shared chrome intact. The same pattern — map a path to a handler, listen for URL changes, update a view region — persists in today's History API-based routers, lazy-loaded component trees, and dynamic route matching. The piece also unpacks the `bind`, `call`, and `apply` mechanics that make the event listener's `this` binding work, a detail that trips up developers reading framework internals.

Takeaways
Multi-page apps reload the full HTML document on every link click, causing white flashes, lost scroll state, and repeated transmission of shared UI.
Hash fragments (`#...`) were designed for in-page anchor scrolling but never trigger a server request or page refresh, which made them usable as client-side page identifiers.
A HashRouter can be built with a plain object routing table, a `hashchange` listener, and a `load()` method that reads `location.hash`, looks up a callback, and updates a container's innerHTML.
`bind`, `call`, and `apply` control what `this` refers to inside event handlers; `bind` creates a permanently bound function, while `call` and `apply` invoke immediately with a specified `this`.
The HTML5 History API (`pushState` / `replaceState`) later enabled clean path-based URLs without hash symbols, while still avoiding full-page reloads.
React Router and Vue Router extend the same core idea with component mounting/unmounting, lazy-loaded route chunks, nested route trees, and dynamic path parameters like `/products/:id`.
Conclusions

The jump from anchor links to client-side routing was not a framework invention but a creative reuse of an existing browser behavior — `hashchange` — that was never intended for application-level navigation.

Frameworks add enormous value in scalability and developer experience, but the distance between a 60-line HashRouter and a production router is mostly engineering robustness, not conceptual novelty.

JavaScript's `this`-binding quirks are not academic edge cases; they are load-bearing details in the simplest possible router, and misunderstanding them breaks the entire dispatch chain.

Concepts & terms
MPA (Multi-Page Application)
A traditional web architecture where each URL corresponds to a separate HTML file served by the server. Navigation triggers a full-page reload, re-fetching and re-rendering all resources including shared UI like navigation bars.
SPA (Single Page Application)
An architecture where the entire site loads as a single HTML page and subsequent navigation is simulated by dynamically replacing DOM content, avoiding full-page refreshes and preserving client-side state.
Hash Routing
A client-side routing technique that uses the URL fragment after the `#` symbol as a page identifier. Because hash changes do not trigger server requests, a `hashchange` event listener can swap page content without a reload.
History API
An HTML5 browser API (`pushState`, `replaceState`, `popstate` event) that allows JavaScript to modify the URL path without causing a page refresh, enabling clean URLs like `/products/42` in SPAs.
Routing Table
A data structure — often a plain object or map — that associates URL patterns or hash values with handler functions or components, forming the lookup core of any router.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗