hash与history路由实现原理

hash路由和history路由原理

  1. vue-router的两种路由模式

  2. hash路由

    1. hash是URL的一个组成部分,由URL地址以#开头到末尾,我们可以使用location.hash获取hash值,a标签就是使用改变hash值来进行页面跳转也可做页面的锚点使用,实现锚点跳转

      <!-- 相当于 router-link --> 
              <a href="./#home">首页</a> | <a href="./#about">关于我们</a> | <a href="./#introduce">公司介绍</a>
               <!-- 路由输出 相当于router-view -->
              <div id="router-view"></div>
       <script src="./js/router.js"></script>
      
    2. 创建一个router.js文件 利用hashchange事件监听hash值的变化

      // 定义一个函数返回一个div元素 接收两个参数 id为页面div id属性 text为页面文本
      const importCom = (id, text) => {
          const el = document.createElement('div')
          el.id = id
          el.innerHTML = text
          return el
      }
      
      // 配置路由表
      const routes = [
              { 
                  path: 'home', 
                  component: importCom('home', '欢迎光临公司首页')
              },
              { 
                  path: 'about', 
                  component: importCom('about', '以客户为中心,以奋斗者为本!')
              },
              { 
                  path: 'introduce', 
                  component: importCom('introduce', '互联网知名企业')
              },
              { 
                  path: 'notFound', 
                  component: importCom('notFound', '页面不能找到!')
              },
          ]
      
      // 添加路由,默认home 
      const router = () => { 
      
          const url = location.hash.slice(1) || 'hom' // 获取hash值 初始页面可能没有 设置默认hash值home
          
          const rootEle = document.querySelector('#router-view') // 获取页面路由输出根节点 
      
          rootEle.innerHTML = '' //清空原内容 
      
          const childEle = routes.find(item => item.path == url)?.component // 查找路由组件
      
          // 页面添加路由组件 
          rootEle.appendChild(childEle ? childEle : routes.find(item => item.path == 'notFound')?.component) 
      }
      
      router() //初始化执行
      
      // hash值变化监听,变化后再次执行router 
      window.addEventListener('hashchange', router)
      
  3. history

    1. history为浏览器URL的记录 有两个方法

      1. putState(state,title,url)

        1. 保留现有的记录,将url加到历史记录中
      2. replaceState(state,title,url)

        1. 将历史记录中的当前页面替换成url
      3. 这两个方法都是为了将当前url储存到历史记录中

      4. title为记录标题 基本不用,使用null,state为合法的js对象,可以用在popstate中,popstate事件在

        1. 用户点击浏览器的前进、后退按钮

        2. 代码中调用history.back() 、history.forward()、history.go()

        3. a 标签的锚点

        4. 当history对象发生变化时,就会触发popState事件。通过event.state可以访问当前历史记录的状态对象的拷贝。

          ​ 当网页加载时,各浏览器对popstate事件是否触发有不同的表现,Chrome 和 Safari会触发popstate事件,而Firefox不会。

      5. 附:e.target.tagName 返回当前标签的大写状态

        location.pathname 返回url中的目录和(或)文件名

    2. 代码实现,与hash的实现方式很类似

       <!-- 相当于 router-link --> 
          <nav id='nav'> <a href="./home">首页</a> | <a href="./about">关于我们</a> | <a href="./introduce">公司介绍</a> </nav> 
          <!-- 路由输出 相当于router-view --> 
          <div id="router-view"></div> 
          <script src="./js/router.js"></script>
      
    3. router.js

      const importCom = (id, text) => { 
          const el = document.createElement('div') 
          el.id = id 
          el.innerHTML = text 
          return el 
      }
      
      /*** 路由表 */ 
      const routes = [ 
          {path: 'home', component: importCom('home', '欢迎光临公司首页')},
          { path: 'about', component: importCom('about', '以客户为中心,以奋斗者为本!')},
          { path: 'introduce', component: importCom('introduce', '互联网知名企业')},
          { path: 'notFound', component: importCom('notFound', '页面不能找到!')}, 
      ]
      
      /*** 添加路由,默认home */ 
      const router = () => { 
          const url = location.pathname.slice(1) || 'home' 
          const rootEle = document.querySelector('#router-view') 
          rootEle.innerHTML = '' 
          const childEle = routes.find(item => item.path == url)?.component 
          rootEle.appendChild(childEle ? childEle : routes.find(item => item.path == 'notFound')?.component) }
          
          //事件委托给a标签绑定事件,监听切换 
          const navEle = document.querySelector('#nav') 
          navEle.addEventListener('click', function (e) { 
              if (e.target.tagName == 'A') { 
                  e.preventDefault() 
                  console.log(e.target.getAttribute('href'))
                  const href = e.target.getAttribute('href').slice(1) 
                  history.pushState(null, `页面标题`, href) // 相当于 push 
                  // history.replaceState(null, `页面标题`, href) //相当于replace 
      
                  // 以上两个方法一样的效果
                  
                  router() // 这里不要忘记执行 
              } 
              })
      
  4. 总结

 hash 模式:

   #后面 hash 值的变化,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新页面通过监听 hashchange 事件可以知道 hash 发生了哪些变化,然后根据 hash 变化来实现更新页面部分内容的操作。

   history 模式:

   history 模式的实现,主要是 HTML5 标准发布的两个 API,pushState 和 replaceState,这两个 API 可以改变 url,但是不会发送请求。这样就可以监听 url 变化来实现更新页面部分内容的操作。

   区别

   url 展示上,hash 模式有“#”,history 模式没有
   刷新页面时,hash 模式可以正常加载到 hash 值对应的页面,而 history 没有处理的话,会返回 404,一般需要后端将所有页面都配置重定向到首页路由
   兼容性,hash 可以支持低版本浏览器和 IE。
   ————————————————
   版权声明:本文为CSDN博主「Zswsown」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
   原文链接:https://blog.csdn.net/weixin_44385241/article/details/109245740
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值