9 vue-router
操作DOM模拟实现hash路由
主要利用了window.addEventLIstener('hashchange',callback)事件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; } .container #box1 { width: 100px; height: 100px; background-color: red; margin: 20px; display:none; } .container #box2 { width: 100px; height: 100px; background-color: blue; margin: 20px; display:none; } </style> </head> <body> <div class="container"> <button class="btn">click</button> <button class="btn1">click</button> <div id="box1"> show box1</div> <div id="box2">show box2</div> </div> <script> const btn=document.querySelector('.btn') const btn1=document.querySelector('.btn1') function render(){ const hash=location.hash if(hash==='#box2'){ box2.style.display="block" box1.style.display="none" } else { box1.style.display="block" box2.style.display="none" } } window.addEventListener('load',render) //页面首次加载时候调用 window.addEventListener('hashchange',render) //hash改变的时候调用 btn.addEventListener('click',function(e){ let length=location.href.length //获取除了hash的url长度 if(location.hash){ length=location.href.indexOf('#') //如果有hash url长度就是hash前面的长度 } location.href=location.href.slice(0,length)+'#box1' // 页面不会刷新 }) btn1.addEventListener('click',function(e){ let length=location.href.length //获取除了hash的url长度 if(location.hash){ length=location.href.indexOf('#') //如果有hash直接url 长度就是 } location.href=location.href.slice(0,length)+'#box2' }) </script> </body> </html>
history模式
history对象是一个栈结构 里面记录着当前浏览器窗口的访问记录(也就是url)url可是包括hash的。也就是hash不一样也会在history历史记录栈中保存下来。即便这个页面没有被刷新(hash切换页面本就不会刷新)
当前浏览器窗口:一个浏览器是可以打开很多个窗口的,每个窗口都有属于自己的history浏览记录。很重要的常识,这里说的histroy切换也只是说在自己窗口里切换。
history的常用方法
history.go/back/forword (这几个方法都是获取浏览器历史记录url) 有的url中携带# 就很自然的触发了hashonchange事件。
而 history.pushState/replaceState添加和修改历史栈记录中的条目。
向当前浏览器窗口里通过pushState和replaceState新增一条记录,当前浏览器窗口url会直接改变,但是页面不会自动刷新(这两点很重要)。
但是如果我们手动刷新,当这个新的url地址不存在,就会报404错。所以需要服务器支持:即使请求地址不存在,也是把首页内容返回客户端,而不是404 try_files $uri $uri/ /onething/index.html;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; } .container #box1 { width: 100px; height: 100px; background-color: red; margin: 20px; display:none; } .container #box2 { width: 100px; height: 100px; background-color: blue; margin: 20px; display:none; } </style> </head> <body> <div class="container"> <button class="btn">click</button> <button class="btn1">click</button> <div id="box1"> show box1</div> <div id="box2">show box2</div> </div> <script> const btn=document.querySelector('.btn') const btn1=document.querySelector('.btn1') function render(){ console.log("render -> render", ) const pathname=location.pathname if(pathname==='/box2'){ box1.style.display='none' box2.style.display='block' }else{ box1.style.display='block' box2.style.display='none' } } window.addEventListener('load',render) //初始化渲染 window.addEventListener('popstate',render) //状态发生改变的时候 btn.addEventListener('click',function(e){ history.pushState({state:'box1'},'title1',location.origin+'/box1') }) btn1.addEventListener('click',function(e){ history.pushState({state:'box2'},'title2',location.origin+'/box2') }) </script> </body> </html>
https://web.jingoal.com/a/b?lang=zh_CN#/workbench/mywallet?_k=em3mu6
Location.href:https://web.jingoal.com/a/b?lang=zh_CN#/workbench/mywallet?_k=em3mu6
location.origin: https://web.jingoal.com
location.hostname: web.jingoal.com
Location.protocol: https:
location.origin: https://web.jingoal.com
Location.search: ?lang=zh_CN
Location.pathname: /a/b
Location.hash: #/workbench/mywallet?_k=em3mu6
至于hash里面也带了问号:vue-router hash的query传参