febobo/JS-EveryDay-Question

JS每日一题:Vue-router有几种模式?如何实现呢?

Opened this issue · 0 comments

20190201问

Vue-router有几种模式?如何实现呢?

在vue-router中有两种模式

  • history
    history 为 HTML5 Api,提供了丰富的router 相关属性, 比如history.back() 就能轻松的做到页面回退
  • hash
    hash router 有一个明显的标志是url 中带有#, 我们可以通过监听url中的hash来进行路由跳转

如何实现

history

在代码实现前,我们先看看history几个api

  • history.pushState 浏览器历史纪录添加记录
  • history.replaceState 修改浏览器历史纪录中当前纪录
  • history.popState 当history 发生变化时触发

在结合代码理解:

class Routers {
    contructor () {
        this.routes = {};
        this.listerPopState()
    }
    init(path) {
        history.replaceState({path: path}, null, path);
        this.routes[path] && this.routes[path]();
    }
    // 将router键值对形式保存
    route(path, callback){
        this.routes[path] = callback;
    }
    push(path) {
        history.pushState({path: path}, null, path);
        this.routes[path] && this.routes[path]();
    }
    listerPopState () {
        // 监听history状态,当发生改变的时候执行相应的回调
        window.addEventListener('popstate' , e => {
            const path = e.state && e.state.path;
            this.routers[path] && this.routers[path]()
        })
    }
}

window.VueRouter = new Routers();
VueRouter.route('/', ()=> console.log('JS'))
VueRouter.route('/detail', ()=> console.log('JS每日一题'))
// 跳转
VueRouter.push('/detail')  // JS每日一题

hash router

上面说过我们可以通过监听url中的hash来进行路由跳转

结合代码理解:

class Routers {
    constructor () {
        this.routes = {}; // 存放路由path及callback
        this.currentUrl = '';
        this.refresh = this.refresh.bind(this);
        window.addEventListener('load', this.refresh, false);
        // 监听路由change调用相对应的路由回调
        window.addEventListener('hashchange', this.refresh, false);
    }
    route(path, callback){
        this.routes[path] = callback;
    }
    push() {
        this.currentUrl = location.hash.slice(1) || '/';
        this.routes[this.currentUrl] && this.routes[this.currentUrl]()
    }
}

window.VueRouter = new Routers();
VueRouter.route('/', ()=> console.log('JS'))
VueRouter.route('/detail', ()=> console.log('JS每日一题'))
// 跳转
VueRouter.push('/detail')  // JS每日一题

题外话

工作中不必太过纠结使用哪种模式,hash模式url中会带有#号,破坏url整体的美观性, history 需要服务端支持rewrite, 否则刷新会出现404现象