当前位置:网站首页>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
边栏推荐
- 数据库中索引原理及填充因子
- Application of acrel-3000web power management system in Duba Expressway
- Android 3年外包工面试笔记,有机会还是要去大厂学习提升,android开发实习面试题
- The input parameter is object, but it was passed as [object object] because it needs to be converted to JSON format
- Notepad++实用功能分享(正则行尾行首替换常用方法、文本比对功能等)
- SAVE: 软件分析验证和测试平台
- How to take the PMP Exam agile on June 25? Share your troubles
- UART protocol timing summary
- Improvement of DC power distribution with open hall current sensor
- 迷茫的测试/开发程序员,不同人有着不同的故事、有着不同的迷茫......
猜你喜欢

Web site SSL certificate

量化投资模型——高频交易做市模型相关(Avellaneda & Stoikov’s)研究解读&代码资源

Detailed process from CPU fetching to sending control and microprogram control principle

List<? Extensions T > and list <? Super T > difference

UART protocol timing summary

return、const、volatile关键字

【红绿灯识别】基于matlab GUI红绿灯识别【含Matlab源码 1908期】

Notepad++实用功能分享(正则行尾行首替换常用方法、文本比对功能等)

DO280OpenShift访问控制--管理项目和账户

How to take the PMP Exam agile on June 25? Share your troubles
随机推荐
String s = new string ("XYZ") how many string objects are created?
SQL Server 中 GO 的用法
跟着CTF-wiki学pwn——ret2text
Unity text component space newline problem
Save: software analysis, verification and test platform
Application of acrel-3000web power management system in Duba Expressway
.NET 中的 Worker Service 介绍
组合总数II[每个元素只能用一次 + 去重复解集]
并发和并行有什么区别?
High imitation Betta app
2021-11-23: Regulations: l[1] corresponds to a, l[2] corresponds to B, l[3] corresponds to C
mcu常用寄存器位操作方式汇总
Windows10 security mode entry cycle blue screen repair
Restore IP address [standard backtracking + standard pruning]
docker 部署redis
人工智能技术岗位面试要注意什么?
[bug] the element in C iqueryable cannot change its value
Docker redis cluster configuration
docker 部署redis
如何利用數倉創建時序錶