Vue中Hash与History模式对比➕手写Hash Router"

975 阅读6分钟

Vue Router 是 Vue.js 官方提供的路由管理器,用于构建单页面应用(SPA)。它与 Vue.js 深度集成,提供了一种声明式的方式来导航和渲染组件,使得在不同的路由间切换变得简单且高效。Vue Router 支持多种特性,包括嵌套路由、导航守卫、过渡动画、懒加载等。

createWebHashHistory vs createWebHistory

createWebHashHistorycreateWebHistory 是 Vue Router 中用于配置不同路由模式的工厂函数。它们都是 Vue Router v4 版本引入的。不过他们之间的区别不是特别的大,我们可以来对比看看。

createWebHashHistory

createWebHashHistory 是 Vue Router 中用于创建使用哈希模式的路由器的工厂函数。哈希模式利用 URL 的哈希部分(即 # 符号后面的部分)来记录路由信息。当用户在应用中导航时,浏览器的 URL 会改变,但页面不会重新加载,因为浏览器只认为 URL 的哈希部分发生了变化。

优点:

  • 兼容性好: 所有浏览器都支持哈希变化,因此哈希模式可以在较旧的浏览器中工作。
  • 无需服务器配置: 由于 URL 的哈希部分不会被服务器端解析,所以不需要对服务器做任何特殊配置。

缺点:

  • URL 不美观: URL 中包含 # 可能会让 URL 看起来不那么好看或者说清晰。

createWebHistory

createWebHistory 用于创建使用 HTML5 History API 的路由器。History 模式下,URL 看起来就像传统的多页面应用那样,没有 # 字符。这意味着 URL 更加简洁和直观。

优点:

  • URL 清晰: URL 没有 #,看起来更像常规的网页链接。
  • SEO(搜索引擎优化) 友好: 对搜索引擎优化更有利,因为搜索引擎爬虫更容易理解不带 # 的 URL。

缺点:

  • 服务器配置: 需要服务器端配置,以便在请求任何路由时都能返回同一个 index.html 文件,否则可能会出现 404 错误。
  • 兼容性问题: 虽然大多数现代浏览器都支持 HTML5 History API,但对于一些老旧浏览器可能不适用。

对比

  1. URL的美观性:

    • createWebHashHistory() : URL中包含#,可能看起来不够专业或整洁,但不需要服务器端做任何额外配置。
    • createWebHistory() : URL中不包含#,更加美观,更接近传统的多页面应用的URL结构,对SEO友好。
  2. 服务器配置:

    • createWebHashHistory() : 不需要服务器端配置,因为URL中的#部分不会被服务器解析,所有的请求都会被解析为同一个入口文件(如index.html)。
    • createWebHistory() : 需要服务器端配置,以便所有非主入口的URL请求都能够被重定向回主入口文件,避免404错误。
  3. 兼容性:

    • createWebHashHistory() : 具有很好的兼容性,几乎所有浏览器都支持URL的哈希变更。
    • createWebHistory() : 虽然现代浏览器广泛支持HTML5的History API,但对于一些旧版浏览器,可能不支持此API。
  4. 性能和用户体验:

    • createWebHashHistory() : 在某些情况下,页面加载和状态转换可能更快,因为浏览器不需要发送额外的请求来确认URL的变更。
    • createWebHistory() : 用户体验可能更好,因为URL的变化更加直观,且在多窗口或标签页中更容易区分不同的应用状态。

选择建议

选择哪种模式取决于你的应用需求和服务器配置。如果服务器已经正确配置来处理 HTML5 History API,那么使用 createWebHistory() 会得到更干净的 URL;如果服务器配置是个问题或者你想简化开发流程,那么使用 createWebHashHistory() 可能更合适。除去这些的话,他们俩也就是有无#的区别

那么#是个什么玩意

这就要说说锚点与锚链接了

在 HTML 中,锚点和锚链接是用于页面内导航的机制。锚点通过 idname 属性定义,而锚链接则使用 href 属性指向某个锚点,格式为 # 加上锚点的 idname

示例:

image.png

运行结果

9a590f8f-c750-4215-bce3-f09c5742aa17.gif

在 Vue Router 的哈希模式下,锚点链接的工作方式与纯 HTML 中相同。当点击这个链接时,浏览器会跳转到 URL + #yilou 这个锚链接, 并在浏览器的地址栏显示#yilou,但是页面不会刷新,只会展示这个锚点的地方。而 Vue Router 的哈希模式就是运用了来自锚链接 的原生能力,点击链接时,url会发生改变 #hash, 用于实现单页应用的路由功能,不会刷新当前的页面,相应的组件显示到router-view位置就好咯,就实现了单页应用的要求。

手写一个Hash Router

  • 首先,我们要先创建一个导航栏, 定义导航栏中的链接,点击链接会改变 URL 的哈希部分。在Vue中我们是使用<router-view></router-view>定义一个路由入口,来显示路由组件的内容。这里我们用原生JS写的话,就用一个id="container"来设置一个容器,用于显示根据哈希值加载的不同内容。

        <nav id="nav">
            <ul>
                <li><a href="#/page1">page1</a></li>
                <li><a href="#/page2">page2</a></li>
                <li><a href="#/page3">page3</a></li>
            </ul>
        </nav>
         <div id="container">
              //在这里显示根据哈希值加载的不同内容
         </div>
    
  • 既然要在id="container"这个容器里操作,就得先拿到这个容器。

  • 还需要监听hashchange事件,拿到点击链接改变的 URL 的哈希部分

  • 然后每当点击链接的时候,往该容器里面添加html代码片段,去展示

  • 那我们就要将链接的哈希部分与html代码片段一一对应。

  • 这样的话,我们就创建一个对象,去存放这些item。

  • 当用户点击链接时,将拿到的哈希部分与对象中的key对比,相同的话就输出展示这个html片段。

  • 那我们需要先将现有的路径存放在对象中,并且设置好首页,当没有点击时先展示首页给用户看。

  • 要是用户自己随意输入了一个路径的哈希部分,而我们并没有,那代码应该不执行。

  • 考虑到复用性,我们直接将HashRouter封装一下。

            //封装一个hashRouter
    
            class HashRouter{
                constructor(){
                    this.routes={};    //page => component 对象
                    window.addEventListener("hashchange",this.load.bind(this),false);
                }
                register(hash,callback=function(){}){
                    this.routes[hash]=callback;
                }   
                registerIndex(callback=function(){}){
                    this.routes["index"]=callback;
                }
                load(){
                    let hash = location.hash.slice(1)//去掉#号 然后就是路由
                    let handler
                    if(!hash){
                        // 去到首页
                        handler = this.routes["index"]
                    }else{
                        // 去相应的页面
                        handler = this.routes[hash]
                    }
                    handler && handler.call(this)  // 确保handler存在才执行后面那个
                }
            }
            let router =new HashRouter()
            let container =document.getElementById("container")
            router.registerIndex(()=>container.innerHTML='我是首页')
            router.register('/page1',()=>container.innerHTML='我是page1')
            router.register('/page2',function(){ container.innerHTML='我是page2' })
            router.register('/page3',()=>container.innerHTML='我是page3')
            router.load() //一开始初始化页面时,先调用一次,展现首页
    
  • 来看看效果怎么样

d0f9170d-7844-4844-a76b-f158eec152a8.gif

总结

通过本文,我们不仅了解了Vue Router中createWebHashHistorycreateWebHistory两种模式的特点与应用场景,还亲自动手实现了一个简易的Hash Router。无论是对于前端开发者还是对单页面应用架构感兴趣的读者,相信都能从中获得宝贵的见解。

选择合适的路由模式对于构建流畅、用户友好的单页面应用至关重要。在实际项目中,应当根据项目的具体需求、目标用户群体以及服务器配置情况综合考量,做出最合理的选择。

如果你对本文有任何疑问或见解,欢迎留言讨论。期待在前端开发的学习旅程中,与你一起加油!