路由是什么?
路由器是用来分发请求的。
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 || 1let 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复制给别人,别人打开时就是默认的页了。
资料来源:饥人谷
