This article mainly records the pushState and replaceStateAPI provided by history in HTML5. Finally, implement small routing yourself through these APIs.
For the API provided by window.history, please refer to the Mozilla documentation
The pushState and replaceState APIs provided by history provide methods for operating the browser history stack.
The pushState:
history.pushState(data, null, '#/page=1'); pushState接收3个参数,第一个参数为一个obj,表示浏览器 第二个参数是document.title的值,一般设定为`null` 第三个参数string,用以改变 当前url
pushState method pushes new history records into the browser history stack while changing the URL.
The parameter that receives the url is of string type, which is used to change the url of the current address bar. One thing to note is that this parameter cannot be the same as cross-domain, that is, the protocol, domain name, and port must be the same. If there is a cross-domain situation, It will prompt:
Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'http://www.baidu.com/' cannot be created in a document with origin 'http://commanderXL.com' and URL
Example:
打开www.baidu.com history.pushState(null, null, '?page=1') //地址栏变成 www.baidu.com/?page=1 history.pushState(null, null, '#page=2'); //地址栏变成 www.baidu.com/#page=2
where replaceState:
history.replaceState(null, null, '#page=2');
replaceState receives the same parameters as pushState, but the final effect is: the address bar url will change according to the received parameters, but the browser is not browsing The browser history is added to the history stack, but the current browser history is replaced.
Although the URL can be changed through pushState and replaceState, it will not actively trigger browser reload.
The window object also provides the popstate method:
window.addEventListener('popstate', function() { });
This method is used to monitor the browser switching between different historical records and trigger corresponding events.
There are also go and back methods on the history object provided by the browser to simulate the user clicking the browser's forward and back buttons. In a certain web application, for example, when the 3499910bf9dac5ae3c52d5ede7383485 tag is clicked, a page jump occurs. At this time, the page goes back after calling the history.back(); method, and the page refreshes at the same time. At this time, window.onpopstate cannot monitor this event. But if the URL is changed through pushState or replaceState without browser refresh, then use history.back() or history.go() so that the popstate event will be triggered.
history.pushState({page: 1}, null, '?page=1'); history.pushState({page: 2}, null, '?page=2'); history.back(); //浏览器后退 window.addEventListener('popstate', function(e) { //在popstate事件触发后,事件对象event保存了当前浏览器历史记录的状态. //e.state保存了pushState添加的state的引用 console.log(e.state); //输出 {page: 1} });
PS: Add ?page=1 to the url through pushState to get the search content through location.search. However, if you change the URL through location.search, it will actively trigger the browser to reload. This feature can be compared with the content about hashing below.
Now that we have a general understanding of the API, where can these methods be applied? A common scenario is that in a single-page application, front-end routing design is completed through these APIs. PushState and replaceState can be used to change the URL without refreshing the browser, and a series of processes can be completed by monitoring the browser history through popstate. Asynchronous actions.
addRoute('/login', function() { //do something }) //路由处理 const routeHandle = (path) => { Router.forEach((item, index) => { if(item.path === path) { item.handle.apply(null, [path]); return true; } }) return false; } //拦截默认的a标签行为 document.addEventListener('click', function(e) { let dataset = e.target.dataset; if(dataset) { if(routeHandle(dataset.href)) { //阻止默认行为 e.preventDefault(); } } })
The general idea is to add routing information through 3499910bf9dac5ae3c52d5ede7383485, then intercept the default behavior of the 3499910bf9dac5ae3c52d5ede7383485 tag, and match it with the registered routing information. If the match is successful, the corresponding handle method is called.
However, the pushState and replaceState methods are not very compatible with lower versions of IE browsers. Therefore, you can downgrade and use hash for routing design.
hash? Please poke me.
You can get the first #(fragment) and the following content on the url through location.hash. At the same time, its content can be rewritten through location.hash without actively triggering browser reload. Are some functions the same as pushState and replaceState? Therefore, in order to be compatible with lower version browsers, routing design can be carried out by monitoring # changes.
So how to monitor? One of the more crude methods is polling.
var oldHash = location.hash; setTimeInterval(function() { if(oldHash !== location.hash) { //do something oldHash = location.hash; } }, 100);
However, H5 also provides an API: hashchange. It can directly replace the polling method above to monitor changes in #.
window.addEventListener('hashchange', function() { routeHandle(locaiton.hash); });
This small routing design can be found on my github.
A little summary:
The above mainly introduces some APIs provided by history and hash related knowledge. In normal times, it can be used in SPA. Gmail uses hash for routing design. Compared to page jumps:
The page only needs to be loaded once. Later page switching can request data through ajax. The page experience is smoother;
You can use local cache to optimize the page experience. The process of switching between different pages is smoother;
can be loaded on demand...
and other practical benefits.