原生js实现一个hash router

228 阅读1分钟

仓库地址:gitee.com/littleboyck…

文件所在位置:router文件夹

  <div><a r-link="#/home">首页</a></div>
  <div><a r-link="#/button">按钮组件</a></div>
  <div><a r-link="#/form">表单组件</a></div>

  <div id="app"></div>
class Router{
        constructor(){
            //缓存route数据信息
            this.routes = {};
            this.ready();
        }

        static isDOM(el){
            el = Array.from(el);
            if(el.length == 0){return false;}
            for(let i = 0,len=el.length; i<len; i++){
                if(el[i].nodeType != (Node.ELEMENT_NODE||Node.DOCUMENT_NODE)){
                    return false;
                }
            }
            return true;
        }

        static getEl(selector){
            if(selector.nodeType != (Node.ELEMENT_NODE||Node.DOCUMENT_NODE)){
                if(/^#[^#\s\b]+$/.test(selector)){
                    selector = document.querySelector(selector)
                }else{
                    selector = document.querySelectorAll(selector)
                }
            }
            return selector;
        }

        static evtListener(el,event,handle){
            el = Router.isDOM(el) ? [...el] : [el];
            el.forEach(el=>el.addEventListener(event,handle));
        }

        static removeListener(el,event,handle){
            el = Router.isDOM(el) ? [...el] : [el];
            el.forEach(el=>el.removeEventListener(event,handle));
        }

        static xhr(options){

        }

        static isHash(val){
            return /^#[^\s\b]+$/.test(val)
        }

        static setTitle(htmlString){
            let result = /<title>([\w\W]*)<\/title>/.exec(htmlString) 
            ,title = result ? result[1] : htmlString;
            //,matches = document.querySelectorAll('title')[0].textContent.match(/^{{([^{}]+)}}$/);
            document.querySelectorAll('title')[0].textContent = title
        }

        //收集routes
        route(path,callback){
            this.routes[path] = callback ? callback : function(){};
        }

        //重定向会改变hash
        redirect(path){
            location.hash != path && (location.hash = path)
        }

        //跳转是内部行为,不改变hash
        forward(path){
            this.routes[path] && this.routes[path].call(this)
        }

        init(firstPath){
            let curHash = location.hash;
            curHash && (firstPath = curHash)
            Router.isHash(firstPath) && (location.hash = firstPath) && curHash && this.forward(firstPath)
        }

        //监听hashchange
        listenerHashchange(){
            Router.evtListener(window,'hashchange',()=>{
                this.forward(location.hash)
            });
        }

        //初始化
        ready(){
            this.listenerHashchange();
        }
    }

使用方式

  const router = new Router()
  //1、注册routes依赖
  router.route("#/home",function(){
      Router.setTitle("首页")
      document.getElementById('content').innerHTML = '欢迎来到首页'
  })
  router.route("#/button",function(){
      $.ajax({
          type:'get'
          ,url:'../component/button.html'
      }).then(function(html){
          Router.setTitle(html)
          document.getElementById('content').innerHTML = html;
      })
  })
  router.route("#/form",function(){
      $.ajax({
          type:'get'
          ,url:'../component/element.html'
      }).then(function(html){
          Router.setTitle(html)
          document.getElementById('content').innerHTML = html;
      })
  })
  //2、初始化默认页
  router.init('#/home')
  //3、点击事件
  Router.evtListener(document.querySelectorAll('[r-link]'),'click',function (e) {
      router.redirect(this.getAttribute('r-link'))
  })