当前位置:网站首页>Principles and differences between hash and history
Principles and differences between hash and history
2022-06-24 00:05:00 【Front end small tips】
Current single page application (SPA) More and more become the front-end mainstream , A major feature of single page applications is the use of front-end routing , The front end directly controls the route jump logic , It is no longer controlled by the back-end personnel , This gives the front end more freedom .
At present, there are two main ways to implement front-end routing :hash Patterns and history Pattern , Here are the details .
1. hash Pattern
For example, when making anchor jump with hyperlinks , You will find ,url Followed by "#id",hash The value is url In the from "#" The part from the beginning to the end of No .
hash When the value changes, the browser will not reissue the request , But it triggers window.hashChange event , If we were hashChange Get the current... From the event hash value , And according to hash Value to modify the page content , The purpose of front-end routing is achieved .
<!-- html: The menu href Set to hash form ,id by app Place page content in -->
<ul id="menu">
<li>
<a href="#index"> home page </a>
</li>
<li>
<a href="#news"> information </a>
</li>
<li>
<a href="#user"> Personal center </a>
</li>
</ul>
<div id="app"></div>// stay window.onhashchange In order to get hash value , According to different values , modify app Different contents in , It has the effect of routing
function hashChange(e){
// console.log(location.hash)
// console.log(location.href)
// console.log(e.newURL)
// console.log(e.oldURL)
let app = document.getElementById('app')
switch (location.hash) {
case '#index':
app.innerHTML = '<h1> This is the home page </h1>'
break
case '#news':
app.innerHTML = '<h1> This is the news </h1>'
break
case '#user':
app.innerHTML = '<h1> This is a personal focus </h1>'
break
default:
app.innerHTML = '<h1>404</h1>'
}
}
window.onhashchange = hashChange
hashChange()The above implementation method is relatively simple , We can package it again :
class Router {
constructor(){
this.routers = [] // Store our routing configuration
}
add(route,callback){
this.routers.push({
path:route,
render:callback
})
}
listen(callback){
window.onhashchange = this.hashChange(callback)
this.hashChange(callback)() // There is no trigger when you first enter the page hashchange, You have to call it alone
}
hashChange(callback){
let self = this
return function () {
let hash = location.hash
console.log(hash)
for(let i=0;i<self.routers.length;i++){
let route = self.routers[i]
if(hash===route.path){
callback(route.render())
return
}
}
}
}
}
let router = new Router()
router.add('#index',()=>{
return '<h1> This is the home page </h1>'
})
router.add('#news',()=>{
return '<h1> This is the news </h1>'
})
router.add('#user',()=>{
return '<h1> This is a personal focus </h1>'
})
router.listen((renderHtml)=>{
let app = document.getElementById('app')
app.innerHTML = renderHtml
})Achieve one Router class , adopt add Method to add a routing configuration , The first parameter is the routing path , The second parameter is render function , Return to the page you want to insert html; adopt listen Method , monitor hash change , And return each route html, Insert into app in . So we have a simple hash route .
2. history Pattern
hash The pattern looks ugly , Bring both "#" Number , We can also take history Pattern ,history It is the normal connection form we usually see .history The pattern is based on window.history Object method .
stay HTML4 in , Has supported window.history Object to control page history jump , Common methods include :
history.forward(): Take a step forward in historyhistory.back(): Step back in historyhistory.go(n): Jump in history n step ,n=0 To refresh this page ,n=-1 To go back one page .
stay HTML5 in ,window.history Object has been extended , Newly added API Include :
history.pushState(data[,title][,url]): Append a record to the historyhistory.replaceState(data[,title][,url]): Replace the current page's information in history .history.state: Is an attribute , You can get the current page state Information .window.onpopstate: It's an event , Click the browser Back button or js callforward()、back()、go()Trigger when . A listening function can be passed in event object ,event.stateThat is, throughpushState()orreplaceState()Method passed in data Parameters
history The pattern principle can be understood in this way , First we need to transform our hyperlinks , Add... To each hyperlink onclick Method , Prevent default hyperlinks from jumping , change to the use of sth. history.pushState or history.replaceState To change... In the browser url, And modify the page content . Because through history Of api adjustment , It does not send a request to the back end , Therefore, the purpose of front-end routing is achieved .
If the user uses the browser's forward and backward buttons , It triggers window.onpopstate event , The listening page modifies the page content according to the routing address .
You don't have to use hyperlinks , Any element can be used as a menu , Just pass in the click event history Adjust it .
<!--html:-->
<ul id="menu">
<li>
<a href="/index"> home page </a>
</li>
<li>
<a href="/news"> information </a>
</li>
<li>
<a href="/user"> Personal center </a>
</li>
</ul>
<div id="app"></div>//js:
// Transform hyperlinks , Prevent default jump , The default jump will refresh the page
document.querySelector('#menu').addEventListener('click',function (e) {
if(e.target.nodeName ==='A'){
e.preventDefault()
let path = e.target.getAttribute('href') // Get the hyperlink href, Change it to pushState Jump , Do not refresh page
window.history.pushState({},'',path) // Modify the url Address
render(path) // according to path, Change page content
}
})
function render(path) {
let app = document.getElementById('app')
switch (path) {
case '/index':
app.innerHTML = '<h1> This is the home page </h1>'
break
case '/news':
app.innerHTML = '<h1> This is the news </h1>'
break
case '/user':
app.innerHTML = '<h1> This is a personal focus </h1>'
break
default:
app.innerHTML = '<h1>404</h1>'
}
}
// Monitor browser forward and backward Events , And render the page according to the current path
window.onpopstate = function (e) {
render(location.pathname)
}
// Enter the page for the first time to display the home page
render('/index')The above writing is too low, We can use classes to encapsulate , adopt add Method to add a route , adopt pushState To jump , Change the jump mode of all hyperlinks during initialization :
class Router {
constructor(){
this.routers = []
this.renderCallback = null
}
add(route,callback){
this.routers.push({
path:route,
render:callback
})
}
pushState(path,data={}){
window.history.pushState(data,'',path)
this.renderHtml(path)
}
listen(callback){
this.renderCallback = callback
this.changeA()
window.onpopstate = ()=>this.renderHtml(this.getCurrentPath())
this.renderHtml(this.getCurrentPath())
}
changeA(){
document.addEventListener('click', (e)=> {
if(e.target.nodeName==='A'){
e.preventDefault()
let path = e.target.getAttribute('href')
this.pushState(path)
}
})
}
getCurrentPath(){
return location.pathname
}
renderHtml(path){
for(let i=0;i<this.routers.length;i++){
let route = this.routers[i]
if(path===route.path){
this.renderCallback(route.render())
return
}
}
}
}
let router = new Router()
router.add('/index',()=>{
return '<h1> This is the home page </h1>'
})
router.add('/news',()=>{
return '<h1> This is the news </h1>'
})
router.add('/user',()=>{
return '<h1> This is a personal focus </h1>'
})
router.listen((renderHtml)=>{
let app = document.getElementById('app')
app.innerHTML = renderHtml
})Of course , The above implementation is only a very rudimentary demo, It cannot be used in real development scenarios , Just to deepen the understanding of front-end routing .
3. hash Patterns and history The difference between patterns
- hash The pattern is ugly ,history The model is more elegant
- pushState Set up new URL It can be related to the current URL Any of the same origin URL; and hash You can only modify # Back section , Therefore, you can only set the URL
- pushState Set up new URL Can be compared with the current URL As like as two peas , This also adds records to the stack ; and hash The new value set must be different from the original value to trigger the record to be added to the stack
- pushState adopt stateObject You can add any type of data to the record ; and hash Only short strings can be added
- pushState Additional settings are available title Property for subsequent use
- hash compatible IE8 above ,history compatible IE10 above
- history The pattern requires back-end cooperation to point all accesses to index.html, Otherwise, the user refreshes the page , It can lead to 404 error
边栏推荐
- Total number of combinations ii[each element can only be solved by + once]
- Detailed process from CPU fetching to sending control and microprogram control principle
- 【第25天】给定一个长度为 n 的数组,统计每个数出现的次数 | 计数哈希
- 微信小程序中three.js的canvas非全屏情况下射线检测不准确问题解决方案
- Cloud native architecture (05) - Application Architecture Evolution
- Improvement of DC power distribution with open hall current sensor
- Under the background of aging, the comprehensive energy efficiency management platform escorts hospitals
- Comment utiliser l'entrepôt de données pour créer une table de synchronisation
- Multi store drug inventory system source code large chain drugstore management system source code
- Startup process analysis of APP performance optimization
猜你喜欢

Android AIDL:跨进程调用Service (AIDL Service),kotlininvoke函数

【数字信号】基于matlab模拟窗函数频谱细化【含Matlab源码 1906期】

Save: software analysis, verification and test platform

AI技术在医学领域有什么用?

点乘和叉乘

fatal: The upstream branch of your current branch does not match the name of your current branch.

docker 部署redis

逆向工具IDA、GDB使用

Improvement of DC power distribution with open hall current sensor

被同事坑到周末加班, 没见过把Redis用成这个鬼样子的。。。
随机推荐
【第25天】给定一个长度为 n 的数组,统计每个数出现的次数 | 计数哈希
Keywords such as extern and struct
== 和 equals 的区别是什么?
String s = new string ("XYZ") how many string objects are created?
Test - use case - detail frenzy
[interview experience package] summary of experience of being hanged during interview (I)
2.摄像机标定
matlab实现对图像批量重命名
复原IP地址[标准回溯+标准剪枝]
Under the background of aging, the comprehensive energy efficiency management platform escorts hospitals
Web site SSL certificate
Detailed process from CPU fetching to sending control and microprogram control principle
Leetcode——链表笔试题
Comment utiliser l'entrepôt de données pour créer une table de synchronisation
解决项目依赖报红问题
Total number of combinations ii[each element can only be solved by + once]
.NET 中的 Worker Service 介绍
Flux in three dimensional vector field
测试 - 用例篇 - 细节狂魔
How to use data warehouse to create time series