History is a new HTML5 standard that is more elegant than Hash, but there are compatibility issues with lower versions of IE.
First, History represents the window’s browsing History, which can be added by pushState or jumped by Go, and the popState event can listen for recorded changes.
What is the basis for implementing a History route
- It needs to change the address without causing the document to jump directly, for example
Hash routing
Because of the URLhash
Changes do not result in document changes; - There needs to be an event to help us listen for this change;
When pushState is used to add a History record, the browser’s address bar is changed, but the browser does not check the address. This allows us to implement elegant routing addresses. For example, https://xxx.com/a, a is the routing address.
To help you understand the code implemented below, take a brief look at pushState
pushState
PushState method, which takes three arguments
- The first is the
state
Take placepopstate
The object passed when the event is called; - Title, which is ignored by the current browser, passed
' '
It is good; - Url, the address to change, be careful to comply with the same origin policy;
For example, if the root path of the current website is https://xxx.com, we use pushState to add a record
history.pushState({ path: "/abc" }, ""."/abc");
Copy the code
The current website is https://xxx.com/abc.
popstate
The pushState event is triggered when the user clicks the forward or backward buttons or calls the history.back (), history.forward (), or history.go () methods.
After the event is fired, there is an event object that has a state property, which is the first argument to the corresponding pushState method.
More information about history can be found at MDN
History route implementation
class Router {
constructor() {
this.routes = new Map(a);this.init();
}
change(e) {
// Prevent null
const { path } = e.state || {};
this.implement(path);
}
init() {
window.addEventListener("popstate".this.change.bind(this));
window.addEventListener("load", () = > {const { pathname } = location;
history.replaceState({ path: pathname }, "", pathname);
this.implement(pathname);
});
}
implement(path) {
if (!this.routes.has(path)) {
return;
}
const fn = this.routes.get(path);
typeof fn == "function" && fn.call(this, path);
}
go(num) {
history.go(num);
}
route(state, fn) {
this.routes.set(state, fn);
}
push(state) {
history.pushState({ path: state }, "", state);
this.implement(state);
}
replace(state) {
history.replaceState({ path: state }, "", state);
this.implement(state); }}Copy the code
I’m not going to go into any more detail here, but the only thing to notice is that you need to listen once the page loads, so you use the load event.
Method of use
<ul>
<li><a href="/">hash1</a></li>
<li><a href="/hash2">hash2</a></li>
<li><a href="/hash3">hash3</a></li>
</ul>
<div><button class="f">forward</button> <button class="b">back</button></div>
Copy the code
const color = {
"/": "yellow"."/hash2": "# 333"."/hash3": "#DDD"
};
const route = new Router();
route.route("/".function(e) {
document.body.style.background = color[e];
});
route.route("/hash2".function(e) {
document.body.style.background = color[e];
});
route.route("/hash3".function(e) {
document.body.style.background = color[e];
});
Array.from(document.links).forEach(fn= > {
fn.addEventListener("click", e => {
e.preventDefault();
const href = fn.href;
const { pathname } = new URL(href);
route.push(pathname);
});
});
const backOff = document.querySelector(".b");
const forward = document.querySelector(".f");
backOff.addEventListener("click", () => route.go(- 1));
forward.addEventListener("click", () => route.go(1));
Copy the code
Notice here that I have directly blocked the default jump of the A link to prevent it from going directly to other documents.
The last
The two implementations of front-end routing are explained here, and the rest is to improve on this principle, such as the processing of 404 pages.
Star if it helps.