当前位置:网站首页>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
边栏推荐
- 【面试经验包】面试被吊打经验总结(一)
- When the IOT network card device is connected to easycvr, how can I view the streaming IP and streaming time?
- [things about gbase] gbase 8s high availability technology and case analysis (issue 02)
- docker 部署redis
- 组合总数II[每个元素只能用一次 + 去重复解集]
- 迷茫的测试/开发程序员,不同人有着不同的故事、有着不同的迷茫......
- Learn PWN from CTF wiki - ret2text
- NLP-D58-nlp比赛D27&刷题D14&读论文&mathtype
- Innovative lampblack supervision in the management measures for the prevention and control of lampblack pollution in Deyang catering service industry (Draft for comments)
- All 32 keyword classifications of C language C89 (C90)
猜你喜欢
![[FreeRTOS] 07 binary semaphore and count semaphore](/img/9c/a3e4b9e02f754c5d3a54d94b7b4e35.png)
[FreeRTOS] 07 binary semaphore and count semaphore

How to take the PMP Exam agile on June 25? Share your troubles

APP性能优化之启动流程分析

合成大西瓜小游戏微信小程序源码/微信游戏小程序源码

What is the use of AI technology in the medical field?

2.摄像机标定

Accompanist组件库中文指南 - Glide篇,劲爆

DO280OpenShift访问控制--管理项目和账户
![复原IP地址[标准回溯+标准剪枝]](/img/e6/5f9d2a5af973b6c7051ed434a4b93d.png)
复原IP地址[标准回溯+标准剪枝]

Android AIDL:跨进程调用Service (AIDL Service),kotlininvoke函数
随机推荐
Under the background of aging, the comprehensive energy efficiency management platform escorts hospitals
matlab实现对图像批量重命名
AI技术在医学领域有什么用?
Don't miss | Huawei's internal data - Successful Project Management PPT (page 123)
微信小程序 图片验证码展示
When the IOT network card device is connected to easycvr, how can I view the streaming IP and streaming time?
Unity text component space newline problem
混沌工程,了解一下
Synthetic big watermelon games wechat applet source code / wechat game applet source code
Android 7,2021最新Android面试笔试题目分享
Android AIDL:跨进程调用Service (AIDL Service),kotlininvoke函数
Startup process analysis of APP performance optimization
The group procurement management system of daily chemical supplies industry changes the traditional procurement mode and reduces the procurement cost
物联网卡设备接入EasyCVR,如何查看拉流IP以及拉流时间?
NLP工程师是干什么的?工作内容是什么?
Leetcode - linked list written test questions
DO280OpenShift访问控制--管理项目和账户
数据库中索引原理及填充因子
元宇宙中的社会秩序
PMP Exam related calculation formula summary! Must see before examination