阅读 311

Javascript 前端路由的简单实现(hash模式和history模式)

Javascript 前端路由的简单实现(hash模式和history模式)

路由是根据不同的url地址来显示不同的页面或内容的功能。 之前的路由主要是后端路由,对应不同的路由,服务端会返回相应的数据(html, json等等),然后浏览器重新解析和渲染。后端路由有一个很大的问题是路由切换的时候会频繁刷新页面,对用户体验来说并不友好。在这个背景之下,前端路由出现了,它可以实现路由切换同时不刷新页面。

在常用的前端框架(Vue, React 等)中,通常会有 hash 路由 和 history 路由两种路由方式。

  • hash 路由:监听 url 中 hash 的变化,渲染不同的内容,这种路由不向服务器发送请求,不需要服务端的支持;

  • history 路由:监听 url 中的路径(path)变化,渲染不同的内容,这种路由不向服务器发送请求,需要客户端和服务端共同的支持;

注意,这里的需要服务端的支持并不是指会向服务器发送请求,而是因为框架和history模式的特性,需要在服务端进行一些配置。如果服务端没有配置新更新的 url ,一刷新浏览器就会报错,因为刷新浏览器会真实地向服务器发送一个 http 的请求。因此若要使用 history 路由,需要服务端的支持。具体可以参考这一篇文章 vue-router history模式 为什么需要服务端配置以及如何配置

一、hash模式

hash模式主要是监听 url 中 hash 的变化,这里就必须提到一个关键的对象 window.location

改变hash不会触发页面跳转,因为hash链接是当前页面中的某个片段,所以如果hash有变化,那么页面将会滚动到hash所连接的位置。但是页面中如果不存在hash对应的片段,则没有任何效果。

属性含义
location.href完整的url
location.protocol当前URL的协议,包括 : ; 比如 https:
location.host主机名和端口号
location.hostname主机名
location.port端口号
location.pathnameurl的路径部分,从 / 开始;
location.search查询参数,从 ? 开始
location.hashhash值,从 # 开始的

可以发现 href = protocol + host(hostname+port) + pathname + search + hash
hash模式主要用到的是location.hash

hash路由的特点:

  1. url中hash值的改变,不会重新加载页面。

  2. 通过hashchange事件可以监听到hash值的变化。

  3. hash值的改变会在浏览器的访问历史中增加一条记录。

注意,

  1. 事件hashchange只会在 hash 发生变化时才能触发,而第一次加载页面时并不会触发这个事件,因此我们还需要监听load事件。

  2. 这两个事件的 event对象 是不一样的:hashchange 事件中的 event 对象有 oldURLnewURL 两个属性,可以从中提取出 preHashcurrentHash 。但是 load 事件中的 event 没有这两个属性,不过我们可以通过 location.hash 来获取到当前的 hash 路由。

1. hash模式的简单实现

//hash路由 class HashRoute {     constructor() {         //存储对象         this.routes = {};         //当前hash         this.currentHash = ''         //绑定this.避免监听时this指向改变         this.freshRoute = this.freshRoute.bind(this);         //监听         // 页面加载事件         window.addEventListener('load', this.freshRoute, false);         // hashchange事件         window.addEventListener('hashmessage', this.freshRoute, false);     }     // 存储     storeRoute(path, callback) {         this.routes[path] = callback || function () { };     }     // 触发     freshRoute() {         this.currentHash = getHash();         let callback = this.routes[this.currentHash]         if (typeof callback === "function") callback()     }     // 获取当前hash值     getHash() {         return location.hash.slice(1) || '/';     } } 复制代码

二、history模式

history模式主要是监听 url 中 path 的变化,这里就必须提到两个关键的对象 window.locationwindow.history

window.history对象的常用方法

方法作用
pushState(obj, title, url)前进到指定的 url,history栈会新增一条记录,不刷新页面
replaceState(obj, title, url)用 url 替换当前的路由,history栈不会新增记录,不刷新页面
forward()前进到下一个路由,如果存在的话
back()后退到上一个路由
go(number)进入到任意一个路由,正数为前进,负数为后退

history路由的特点:

  1. url中path值的改变,不会重新加载页面。

  2. 通过popstate事件可以监听到path值的变化。

注意,

  1. 和hash路由一样,popstate事件只会在 history 发生变化时才能触发,而第一次加载页面时并不会触发这个事件,因此我们还需要监听load事件。

  2. pushStatereplaceState被调用时,不会触发触发 popstate 事件的,但是我们可以使用window.dispatchEvent来添加事件。

1. history模式的简单实现

//history路由 class HistoryRoutes {     constructor() {         //存储对象         this.routes = {};         //当前path         this.currentPath = '';         //绑定this.避免监听时this指向改变         this.freshRoute = this.freshRoute.bind(this);         //监听事件         window.addEventListener('load', this.freshRoute, false);         window.addEventListener('popstate', this.freshRoute, false);         window.addEventListener('pushState', this.freshRoute, false);         window.addEventListener('replaceState', this.freshRoute, false);     }     // 存储     storeRoute(path, callback) {         this.routes[path] = callback || function () { };     }     // 触发     freshRoute() {         this.currentPath = this.getState();         this.routes[this.currentPath] && this.routes[this.currentPath]();     }          // 初始化     init(path) {         history.replaceState(null, null, path);         this.routes[path] && this.routes[path]();     }     // 跳转     go(path) {         history.pushState(null, null, path);         this.routes[path] && this.routes[path]();     }          // 获取路由路径     getState() {         const path = window.location.pathname;         return path ? path : '/';     } }


作者:Happyileaf
链接:https://juejin.cn/post/7031561396554825741


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐