一个简单的前端 router hash 模式实现

简介: 最近做的业务展现在 app 重的 webview 里,app 提供的 webview 框架是默认有底部返回按钮的。pm 希望前端外部页面的框架保持不变,框架中展现的卡片页面可以点击返回按钮进行切换返回。于是想到了用一个简易的前端 router 来实现。

最近做的业务展现在 app 重的 webview 里,app 提供的 webview 框架是默认有底部返回按钮的。pm 希望前端外部页面的框架保持不变,框架中展现的卡片页面可以点击返回按钮进行切换返回。于是想到了用一个简易的前端 router 来实现。

需求

我们这里其实只是想要控制浏览器的 history, 有 push、replace、back 功能就好了,看上去并不需要一个完整的router,但防止之后有需要,页面匹配也加上了。

原理

使用 hash 模式实现前端 router 的原理主要是利用了 url 中 hash 的以下特性:

  • hash 变化时,浏览器不会刷新页面。
  • hash 变化时,会在浏览器中产生一条浏览记录。
  • hash 的变化可以通过 hashchange 事件进行监听。

实现

现在我们分别来看看各个功能是如何实现的

页面控制

add(re, handler) {
    if (typeof re === 'function') {
        handler = re;
        re = '';
    }
    this.routes.push({re, handler});
    return this;
},
check(f) {
    const fragment = f || this.getFragment();
    for (let i = 0; i < this.routes.length; i++) {
        const match = fragment.match(this.routes[i].re);
        if (match) {
            match.shift();
            this.routes[i].handler.apply({}, match);
            return this;
        }
    }
    return this;
},
listen() {
    let current = this.getFragment();
    window.addEventListener('hashchange', () => {
        if (current !== this.getFragment()) {
            current = this.getFragment();
            this.check(current);
        }
    });
    return this;
},
复制代码

页面控制主要是通过三个函数来实现的。

add 函数用来添加一个页面,一个页面通过一个正则和对应的 handler 来定义。

check 函数在 hash 变化时进行正则匹配找到当前 hash 值对应的 handler 执行。

listen 函数监听 hash 的变化,调用 check 函数。

push

push(path = '') {
    window.location.hash = path;
    return this;
},
复制代码

push 方法通过直接改变 window.location.hash 的值来实现,这个和在浏览器中手动改变 hash 是一样的。

replace

replace(path = '') {
    const i = window.location.href.indexOf('#');
    window.location.replace(
        window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path
    );
},
复制代码

replace 的实现利用了 indow.location.replace 方法,这里需要只进行 hash 的替换。

back

back() {
    window.history.back();
}
复制代码

back 更加简单。

code


/** * @file simple router * @author meixuguang */ export default { routes: [], getFragment() { let fragment = ''; const match = window.location.href.match(/#(.*)$/); fragment = match ? match[1] : ''; return this.clearSlashes(fragment); }, clearSlashes(path) { return path.toString().replace(/\/$/, '').replace(/^\//, ''); }, add(re, handler) { if (typeof re === 'function') { handler = re; re = ''; } this.routes.push({re, handler}); return this; }, remove(param) { for (let i = 0, r; i < this.routes.length, r = this.routes[i]; i++) { if (r.handler === param || r.re.toString() === param.toString()) { this.routes.splice(i, 1); return this; } } return this; }, flush() { this.routes = []; return this; }, check(f) { const fragment = f || this.getFragment(); for (let i = 0; i < this.routes.length; i++) { const match = fragment.match(this.routes[i].re); if (match) { match.shift(); this.routes[i].handler.apply({}, match); return this; } } return this; }, listen() { let current = this.getFragment(); window.addEventListener('hashchange', () => { if (current !== this.getFragment()) { current = this.getFragment(); this.check(current); } }); return this; }, push(path = '') { window.location.hash = path; return this; }, replace(path = '') { const i = window.location.href.indexOf('#'); window.location.replace( window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path ); }, back() { window.history.back(); }, go(n) { window.history.go(n); } };


原文发布时间为:2018年07月02日
作者:芦梦宇
本文来源: 掘金  如需转载请联系原作者






相关文章
|
4天前
|
前端开发 算法 Java
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
Flex 布局 布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。 2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。 一、Flex 布局是什么? Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
90 1
|
10月前
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
511 11
|
移动开发 前端开发 JavaScript
浅谈前端路由原理hash和history
该文章详细解析了前端路由的两种模式——Hash模式与History模式的工作原理及其实现方式,并通过实例代码展示了如何在实际项目中运用这两种路由模式。
|
前端开发
前端web入门第四天】03 显示模式+综合案例热词与banner效果
本文档介绍了HTML中标签的三种显示模式:块级元素、行内元素与行内块元素,并详细解释了各自的特性和应用场景。块级元素独占一行,宽度默认为父级100%,可设置宽高;行内元素在同一行显示,尺寸由内容决定,设置宽高无效;行内块元素在同一行显示,尺寸由内容决定,可设置宽高。此外,还提供了两个综合案例,包括热词展示和banner效果实现,帮助读者更好地理解和应用这些显示模式。
140 6
|
12月前
|
JavaScript 前端开发 应用服务中间件
Vue开发中,在实现单页面应用(SPA)前端路由时的hash模式和history模式的区别及详细介绍
Vue开发中,在实现单页面应用(SPA)前端路由时的hash模式和history模式的区别及详细介绍
402 0
|
设计模式 JavaScript 前端开发
Vue.js 组件设计模式:在前端热潮中找到归属感,打造可复用组件库,开启高效开发之旅!
【8月更文挑战第22天】Vue.js 以其高效构建单页应用著称,更可通过精良的组件设计打造可复用组件库。组件应职责单一、边界清晰,如一个显示文本并触发事件的按钮组件,通过 props 传递标签文本,利用插槽增强灵活性,允许父组件注入动态内容。结合 CSS 预处理器管理和封装独立模块,配以详尽文档,有效提升开发效率及代码可维护性。合理设计模式下,组件库既灵活又强大,持续实践可优化项目工作流。
174 1
|
前端开发 JavaScript 开发者
条件判断的模式问题之为什么不建议在前端日常业务开发中使用OOP的责任链模式实践
条件判断的模式问题之为什么不建议在前端日常业务开发中使用OOP的责任链模式实践
125 2
|
缓存 前端开发 安全
探索现代Web开发中的前端架构模式
【6月更文挑战第23天】随着互联网技术的飞速发展,前端架构在Web开发中扮演着越来越重要的角色。本文将深入探讨现代Web开发中使用的几种主流前端架构模式,包括单页面应用(SPA)、微前端架构和JAMStack等,并分析它们的优势与应用场景。通过实例演示,我们将看到如何根据项目需求选择合适的前端架构,以及如何利用这些架构模式提升开发效率和应用性能。
|
前端开发 搜索推荐 开发者
【Flutter前端技术开发专栏】Flutter中的自定义主题与暗黑模式
【4月更文挑战第30天】本文介绍了如何在Flutter中自定义主题和实现暗黑模式。通过`ThemeData`类定义应用的外观,包括颜色、字体和样式。示例展示了如何设置主色、强调色及文本、按钮主题。暗黑模式可通过`darkTheme`属性启用,结合`ThemeData.dark()`方法定制。利用`MediaQuery`监听系统亮度变化,动态调整暗黑模式状态。Flutter的这些特性有助于开发者创建独特且用户友好的界面。
619 0
【Flutter前端技术开发专栏】Flutter中的自定义主题与暗黑模式
|
前端开发 UED
前端事件驱动模式如何提高用户体验和应用程序的交互性
前端事件驱动模式提升用户体验,实现即时响应、动态更新界面、精确处理交互、创建用户友好界面和增强可扩展性。通过监听用户操作触发事件处理,实现流畅、直观的交互,如表单验证、输入补全、拖拽排序等。模块化设计便于功能扩展和维护,打造响应式、用户中心化的应用。