一个简单的前端 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日
作者:芦梦宇
本文来源: 掘金  如需转载请联系原作者






相关文章
|
3月前
|
设计模式 存储 缓存
精进前端开发:深入探讨前端设计模式
精进前端开发:深入探讨前端设计模式
30 0
|
3月前
|
前端开发 搜索推荐 UED
解密前端路由: hash模式vs.history模式
解密前端路由: hash模式vs.history模式
|
4月前
|
设计模式 前端开发 JavaScript
前端设计模式之【迭代器模式】
前端设计模式之【迭代器模式】
36 0
|
4月前
|
移动开发 前端开发 JavaScript
VSCode设置类似Webstorm那样可以用本地局域网IP地址访问自己开发的测试项目,vs code 前端如何以服务器模式打开?
VSCode设置类似Webstorm那样可以用本地局域网IP地址访问自己开发的测试项目,vs code 前端如何以服务器模式打开?
VSCode设置类似Webstorm那样可以用本地局域网IP地址访问自己开发的测试项目,vs code 前端如何以服务器模式打开?
|
3月前
|
设计模式 算法 前端开发
【面试题】如何理解 前端设计模式-测策略模式?
【面试题】如何理解 前端设计模式-测策略模式?
|
3月前
|
前端开发
前端必看的8个HTML+CSS技巧 (七)混合模式(Blend)
前端必看的8个HTML+CSS技巧 (七)混合模式(Blend)
|
4月前
|
设计模式 前端开发 JavaScript
前端设计模式之【外观模式】
前端设计模式之【外观模式】
35 0
|
4月前
|
设计模式 前端开发 算法
前端设计模式之【访问者模式】
前端设计模式之【访问者模式】
26 0
|
4月前
|
设计模式 前端开发 JavaScript
前端设计模式之【观察者模式】
前端设计模式之【观察者模式】
30 0
|
4月前
|
设计模式 前端开发 Java
前端设计模式之【单例模式】
前端设计模式之【单例模式】
24 0