Vue Router offers two routing strategies: the hash mode and the history mode. While both enable client-side navigation in single-page applications (SPAs), they operate differently under the hood and each has its own trade-offs.
How Hash Mode Works
The hash mode relies on the hashchange event. When the URL hash (the part after #) changes, the browser fires this event without making a server request. Here's a minimal example:
window.addEventListener('hashchange', function(e) {
console.log('Old URL:', e.oldURL);
console.log('New URL:', e.newURL);
const hashValue = location.hash.substring(1);
document.body.style.backgroundColor = hashValue;
});
In this snippet, modifying the hash updates the page's background color. The browser records each hash change in the session history, so the back and forward buttons work as expected. This behavior forms the basis of front‑end routing: mapping URL fragments to different application states without reloading the page.
Popular services like NetEase Cloud Music and Baidu Netdisk use hash routing, resulting in URLs such as:
http://music.163.com/#/friend
https://pan.baidu.com/disk/home#list/vmode=list
How History Mode Leverages the History API
The HTML5 History API gives developers full control over the browser's navigation history, allowing manipulation of the entire URL path, not just the hash fragemnt.
Navigating Through History
Three methods control navigation:
history.go(n)– moves forward or backward by n steps.history.back()– equivalent to pressing the browser's back button.history.forward()– equivalent to pressing the forward button.
Modifying the History Stack
The pushState and replaceState methods alter the history stack without triggering a page load. Each accepts three arguments: a state object, a title (currently ignored by most browsers), and a URL.
// Push a new entry
history.pushState({ color: 'red' }, '', '/red');
// Listen for popstate to restore state
window.addEventListener('popstate', function(e) {
const state = e.state;
if (state && state.color === 'red') {
document.body.style.backgroundColor = 'red';
}
});
// Simulate back / forward navigation
history.back();
history.forward();
When the user navigates back to a pushed URL, the popstate event fires, and the state object can be used to restore the associated page state (scroll position, component toggle, etc.). This enables a clean, hash‑free URL scheme.
The Achilles’ Heel of History Mode
While history mode eliminates the hash (#), it introduces a critical issue: refreshing the page. In hash mode, the server never sees the hash part, so a refresh always works. In history mode, a refresh or direct URL entry sends the full path to the server. If the server has no matching route or resource, it returns a 404 error.
For example, if you host a single‑page blog on GitHub Pages, you should stick with hash mode because GitHub Pages does not automatically serve the index.html for arbitrary paths. History mode would require server‑side fallback configuration.