前端路由 hash和history 原理

239 阅读2分钟

一. hash

锚点使用方式
  1. 超链接方式
  2. location.hash 方式
  3. location.href 方式
1. <a href="#anchor1"> 跳转到锚点1</a>
2. location.hash='anchor1'
3. location.href='anchor1'

注意:
① 当hash值发生变化时,会出发 onhashchange 事件.
② location.hash 前后赋相同值时 不会多次触发 而location.href 可以多次触发

<div name="anchor1" >锚点1</div>
<div name="anchor2" >锚点2</div>
 // or
<div id="anchor1" >锚点1</div>
<div id="anchor2" >锚点2</div>

当hash发生变化时,地址栏地址会发生变化,但是并不会向服务器重新发现请求,页面不会刷新

二. history

History 对象属性
属性名描述
length浏览器历史列表中的 URL 数量
scrollRestoration允许 web 应用程序在历史导航上显式地设置默认滚动恢复行为。此属性可以是自动的(auto)或者手动的(manual)
state(只读)浏 览器在当前URL下的一个状态信息。默认是null
History 对象方法
方法名描述
back()加载 history 列表中的前一个
forward()加载 history 列表中的下一个 URL
go(number丨URL)跳转到指定页面,参数url字符串(不是标准规则)
pushState(state, title, url)向当前浏览器会话的历史堆栈中添加一个状态
replaceState(state, title, url)修改当前历史记录实体

浏览器的前进后退,back(), forward(), go() 会出发window.onpopstate 事件

路由的实现

url路由三种变化的方式

  1. 在页面通过事件修改地址
  2. 浏览器的前进后退,back(), forward(), go() 导致地址栏发生变化
  3. 在地址栏直接输入访问

所以无论是 hash模式 还是history模式.我们只要对着3种操作进行监控就可以实现前端路由功能

① 通过事件修改地址


<body>
    <button id="button">修改url</button>
    <div id="view" />
</body>

<script>
    const button = document.getElementById("button")
    const view = document.getElementById("view")
    
    // hash 模式
    button.onclick = () => {
        location.hash='componentOne'
        if(location.hash==="#componentOne"){
              content.innerHTML="组件1"
        }}
        //or
    //history 模式
     button.onclick = () => {
         history.pushState({ componentId: 1 }, "", "/componentOne")
       if(location.pathname==="/componentOne"){
             content.innerHTML="组件1"
         }}

</script>


点击按钮时通过判断hash或pathname 去渲染对应的组件 ,并且通过 location.hash和 history.pushState 去修改url地址 ,从而达到不刷新浏览器而修改地址

②通过 前进后退修改地址

<script>

    // hash 模式
    window.addEventListener('hashchange',()=>{
       if(location.hash==="#componentOne"){
             content.innerHTML="组件1"
         }}
    )
        //or
    //history 模式
    window.addEventListener('popstate',()=>{
       if(location.pathname==="/componentOne"){
             content.innerHTML="组件1"
         }}
    }

</script>

前进后退,back(), forward(), go() 会触发 onhashchange和onpopstate
③ 在地址栏直接输入访问

<script>
    // hash 模式
  window.addEventListener("DOMContentLoaded", () => {
     if(location.hash==="#componentOne"){
             content.innerHTML="组件1"
         }}
   })
   
       //history 模式
     window.addEventListener("DOMContentLoaded", () => {
       if(location.pathname==="/componentOne"){
             content.innerHTML="组件1"
         }}
   })
 </script>

dom 渲染完成后触发事件, 注意history模式时候 需要后端配合 将路径 '/a/xxxxx' 重新定向到 '/a' 地址上