路由是什么?
路由器是用来分发请求的。
html:
<body>
<a href="#1">go to 1</a>
<a href="#2">go to 2</a>
<a href="#3">go to 3</a>
<a href="#4">go to 4</a>
<div id="app"></div>
<div id="div1" style="display:none">1</div>
<div id="div2" style="display:none">2</div>
<div id="div3" style="display:none">3</div>
<div id="div4" style="display:none">4</div>
</body>
<script src="src/index.js"></script>
index.js
console.log(window.location.hash) //打印#几
let number = window.location.hash.substr(1) //取#号后面的部分
let div = document.querySelector(`#div${number}`) //根据id获取元素
let app = document.querySelector("#app")
div.style.display = "block" //渲染界面
if(app) app.appendChild(div) //展示界面
window.addEventListener('hashchange',()=>{
console.log('hash 变了')
const number2 = window.location.hash.substr(1)
const div2 = document.querySelector(`#div${number2}`) //根据id获取元素
let app2 = document.querySelector("#app")
div2.style.display = "block"
app2.children[0].style.display = "none"
document.body.appendChild(app2.children[0])
app2.appendChild(div2)
})
优化代码
如果url里没有写#号及后面数字,会报错。所以需要默认路由。
如果url里#号后面没有写正确的路由跳转,就需要保底路由/404路由来解决报错。
function route(){
let number = window.location.hash.substr(1)
let app = document.querySelector("#app")
number = number || 1
let div = document.querySelector(`#div${number}`)
if(!div){
div = document.querySelector("#div404")
}
div.style.display = "block"
if(app.children.length > 0){
app.children[0].style.display = "none"
document.body.apendChild(app.children[0])
}
app.appendChild(div)
}
route()
window.addEventListener("hashchange",()=>{
console.log("hash 变了")
route()
})
路由表
为什么url的#号后面一定要写div几呢!hash和div的对应关系,我希望能自定义。
//路由表开始
const div1 = document.createElement('div')
div1.innerHYML = '1'
const div2 = document.createElement('div')
div2.innerHYML = '2'
const div3 = document.createElement('div')
div3.innerHYML = '3'
const div4 = document.createElement('div')
div4.innerHYML = '4'
const routeTable = {
'1':div1,
'2':div2,
'3':div3,
'4':div4
}
//路由表结束
function route(){
let number = window.location.hash.substr(1)
let app = document.querySelector('#app')
number = number || 1
//
let div = routeTable[number.toString()] //使用路由表
...
...
}
嵌套路由/子路由
//路由表开始
const div1 = document.createElement('div')
div1.innerHYML = '1'
const div2 = document.createElement('div')
div2.innerHYML = '2'
const div3 = document.createElement('div')
div3.innerHYML = '3'
const div4 = document.createElement('div')
div4.innerHYML = '4'
const routeTable = {
'1':div1,
'2':div2,
'3':div3,
'4':div4
}
//路由表结束
//子路由表开始
const div11 = document.ceeateElement('div')
div11.innerHTML = '1.1'
const div12 = document.ceeateElement('div')
div12.innerHTML = '1.2'
const route1Table = {
'1/1':div11,
'1/2':div12
}
//子路由表结束 子路由,访问url时这样写:#1/1
hash、history、memory模式
hash,任何情况下都可以用hash模式,缺点是SEO不友好,因为服务器收不到#号及后面的内容。
history,后端将所有前端路由都渲染同一页面,但不能是404页面。例如都渲染为主页。缺点是IE8下不支持。
history
...省略号,上方是路由表
function route(container){
let number = window.location.pathname //是路径名,以/开头
console.log("number:" + number)
number = number || '/1'
//获取界面
let div = routeTable[number.toString()]
if(!div){
div = document.querySelector("#div404")
}
div.style.display = "block"
//展示界面
container.innerHTML = ""
container.appendChild(div)
}
const allA = document.querySelectorAll("a.link")
for(let a of allA){
a.addEventListener("click",e=>{
e.preventDefault()
const href = a.getAttribute("href")
window.history.pushState(null,`page ${href}`,href)
//通知
onStateChange(href)
})
}
route(app)
function onStateChange(){
console.log('state 变了')
route(app)
}
memory
用对象来存储,而不是像hash和history一样将要去的地方写在url中。例如用localStorage。
适合非浏览器,比如app。
缺点是没有用url。因为将url复制给别人,别人打开时就是默认的页了。
资料来源:饥人谷