1. hash路由实现
    1. 如何获取当前hash
    2. 监听hash改变事件
    3. 监听load(页面/加载)事件
    4. 何时注册“/”路由?
    5. 地址栏的编码问题

hash路由实现

众所周知,当我们的浏览器地址栏改变时会刷新页面.
然而hash却不会
hash即地址后的”#/123”类似的字符串
所以利用它我们可以做前端路由

实现的几个关键点(注意this是全局作用域中(非严格模式)):

  1. 如何获取当前hash

    location.hash      //"#/123"
  2. 监听hash改变事件

    this.addEventListener('hashchange',function(){},false);
  3. 监听load(页面/加载)事件

    监听的目的是为了用户在得到这段地址时,如果想在新的标签栏直接打开,此时并不会触发hash改变事件,所以我们要补充一个load事件

    this.addEventListener('load',function(){},false);
  4. 何时注册“/”路由?

    个人建议在this.onload时
    写这个点的原因是我在一开始写的时候,是这么写”/“路由的回调函数的

    location.href = 'http://localhost:8080';

    意思是重新加载主页
    如果不在onload时候注册,就会因为监听了load事件造成页面无限循环加载
    ps:不过后来不这么写了,2333

  5. 地址栏的编码问题

    地址栏获取到的字符编码和你js注册时候的字符编码是不一样的,因此比较时会不相等,造成不存在此路由
    需要unescape([String])

下面实践:

let router=(function(){
  return {
    routes: {},
    //模糊路由,即你无法在本地捕捉到准确数据
    vagueRoutes: [],
    vagueRoutesFun: [],
    //当前路由
    nowUrl: '',

    route: function (url, callback) {
      //路由注册,传入字符串
      this.routes[url]=callback||function () {};
    },
    vagueRoute: function (reg, callback) {
      //模糊路由注册,传入正则表达式
      this.vagueRoutes.push(reg);
      this.vagueRoutesFun.push(callback);
    },
    refresh: function () {
      //路由执行
      this.nowUrl=window.location.hash.slice(1)||'/';
      try{
        this.routes[this.nowUrl]();
      }catch(err){
        //计数器
        let num=0;
        this.vagueRoutes.forEach(function (item,index) {
          if(item.test(this.nowUrl)){
            this.vagueRoutesFun[index]();
            num--;
          }
          num++;
        },this);
        if(num===this.vagueRoutes.length&&this.nowUrl!='/'){
          //不存在的页面处理方式
        }
      }
    },
    init: function () {
      //初始化
      window.addEventListener('load', router.refresh.bind(router));
      window.addEventListener('hashchange', router.refresh.bind(router));
      window.onload = function () {
        router.route('/', function () {
          location.href = 'http://localhost:8080/';
        })
      }
    }
  }
})();