原生js实现一个history router路由

202 阅读1分钟
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>simple history router</title>
</head>
<body>
    <!-- (**组件**)必须放到一个根容器中 -->
    <div><a r-link="/home">首页</a></div>
    <div><a r-link="/intro">介绍页</a></div>
    <div><a r-link="/test">测试页</a></div>

    <div id="content">

    </div>
    <script>
        //replaceState(jsObject,title[多数浏览器忽略此参数],url)
        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 evtListener(els,event,callback){
                els = Router.isDOM(els) ? [...els] : [els];
                els.forEach(el=>el.addEventListener(event,callback));
            }

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

            //跳转至指定path
            go(path){
                history.pushState({path:path},null,path);
                //执行回调
                this.routes[path] && this.routes[path].call(this)
            }

            init(firstPath){
                history.replaceState({path:firstPath},null,firstPath);
                //加载默认的内容页
                this.routes[firstPath] && this.routes[firstPath].call(this)
            }
            
            //监听popstate
            listenerPopstate(){
                Router.evtListener(window,'popstate',(e)=>{
                    let path = e.state && e.state.path;
                    this.routes[path] && this.routes[path].call(this)
                });
            }

            //初始化
            ready(){
                this.listenerPopstate();
            }
        }
    </script>
    <script>
        let router = new Router();
        let targets = document.querySelectorAll('[r-link]');
        //注册routes依赖
        let pathEl = [...document.querySelectorAll('[r-link]')];
        pathEl.forEach(el=>{
            let path = el.getAttribute('r-link')
            ,txt = el.innerHTML;
            router.route(path,function(){
                document.getElementById('content').innerHTML = txt;
            })
        })    
        //初始化默认页
        router.init('/home') 
        Router.evtListener(document.querySelectorAll('[r-link]'),'click',function (e) {
            router.go(this.getAttribute('r-link'))
        })
    </script>
</body>
</html>