手写单页面应用路由
hash模式
<html>
<head>
<meta charset="UTF-8">
<title>Hash</title>
<style>
.nav_container {
display: grid;
justify-content: center;
width: 100%;
height: 80px;
background: #000;
grid-template-columns: repeat(auto-fit, minmax(100px, max-content));
grid-template-rows: 80px;
}
.nav_container > div a {
display: block;
height: 100%;
color: #fff;
padding: 0 30px;
line-height: 80px;
cursor: pointer;
}
.nav_container > div a.ac {
color: red !important;
}
a:link {
color:white;
}
a:visited {
color:white;
}
a:hover {
color:white;
}
</style>
</head>
<body>
<!-- <div id="test">Hello</div>-->
<!-- <div style="height: 2000px"></div>-->
<!-- <div style="cursor: pointer; position: fixed; right: 0; bottom: 0;"><a href="#test">⬆️</a></div>-->
<div class="nav_container">
<div><a class="ac" href="#home">Home</a></div>
<div><a href="#about">About</a></div>
<div><a href="#contact">Contact</a></div>
<div><a href="#other">Other</a></div>
</div>
<div id="app"></div>
</body>
<script>
const app = document.querySelector('#app');
const nav = document.querySelector('.nav_container');
const nav_child = document.querySelectorAll('.nav_container div a')
function init() {
nav.addEventListener('click', (e)=> {
console.log(e.parentNode);
if(e.target.nodeName === 'A') {
nav_child.forEach(el => {
el.className = '';
});
e.target.className = 'ac';
}
})
console.log(nav_child, nav);
}
init();
const routerCompMap = new Map([
["#home", "<h1>home</h1>"],
["#about", "<h1>about</h1>"],
["#contact", "<h1>Contact</h1>"]
]);
function renderPage(hash) {
const domStr = routerCompMap.get(hash) || "<h1>404</h1>";
app.innerHTML = domStr;
console.log("domStr", domStr);
}
document.addEventListener('DOMContentLoaded', ()=> {
window.addEventListener('hashchange', ()=> {
renderPage(window.location.hash);
});
renderPage(window.location.hash || '#home');
})
</script>
</html>
history模式
<html>
<head>
<meta charset="UTF-8">
<title>history</title>
<style>
.nav_container {
display: grid;
justify-content: center;
width: 100%;
height: 80px;
background: #000;
grid-template-columns: repeat(auto-fit, minmax(100px, max-content));
grid-template-rows: 80px;
}
.nav_container > div a {
display: block;
height: 100%;
color: #fff;
padding: 0 30px;
line-height: 80px;
cursor: pointer;
}
.nav_container > div a.ac {
color: red !important;
}
a:link {
color:white;
}
a:visited {
color:white;
}
a:hover {
color:white;
}
a[data-link] {
font-size: 30px;
}
</style>
</head>
<body>
<div class="nav_container">
<div><a class="ac" href="/home" data-link>Home</a></div>
<div><a href="/about" data-link>About</a></div>
<div><a href="/contact" data-link>Contact</a></div>
<div><a href="/other" data-link>Other</a></div>
</div>
<div id="app"></div>
<script>
let app = document.querySelector('#app');
const routerCompMap = new Map([
["/home", "<h1>home</h1>"],
["/about", "<h1>about</h1>"],
["/contact", "<h1>Contact</h1>"]
]);
function renderPage(hash) {
const domStr = routerCompMap.get(hash) || "<h1>404</h1>";
app.innerHTML = domStr;
console.log("domStr", domStr);
}
document.addEventListener('DOMContentLoaded', ()=> {
renderPage('/home');
document.querySelectorAll('a[data-link]').forEach(el => {
el.addEventListener('click', (e)=> {
e.preventDefault();
let path = e.target.getAttribute('href');
history.pushState(null, null, path);
renderPage(path);
console.log(path);
})
})
});
</script>
</body>
</html>
hash和history模式的区别
- 外观:hash的url有个#符号,history没有,history外观更好看。
- 刷新:hash刷新会加载到地址栏对应的页面,history刷新浏览器会重新发起请求,如果服务端没有匹配当前的url,就会出现404页面。
- 兼容性:hash能兼容到IE8,history只能兼容到IE10。
- 服务端支持:hash(#及后面的内容)的变化不会导致浏览器向服务器发起请求;history刷新会重新向服务器发起请求,需要在服务端做处理:如果没有匹配到
- 原理:hash通过监听浏览器的onhashchange()事件,查找对应的路由规则;history利用H5新增的pushState()和replaceState()方法改变url。
- 记录:hash模式只有#后面的内容被修改才会添加新的记录栈;history通过pushState()设置的url于当前url一模一样也会被记录到历史记录栈。
本文作者:HuangBingQuan
本文链接:https://www.cnblogs.com/bingquan1/p/18572692
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-11-27 React类组件的生命周期