原生js实现一个hash路由

仓库地址:https://gitee.com/littleboyck/front.git

目录所在位置:router文件夹

index.html的<body><div id="app"></div>

 <script src="./lib/Router.js"></script>
view文件夹中新建layout.html

<div class="layout-fluid">
    <div><a r-link="#/home">首页</a></div>
    <div><a r-link="#/button">按钮组件</a></div>
    <div><a r-link="#/form">表单组件</a></div>
    <div><a r-link="#/bdage">徽章组件</a></div>
    <div id="app-body" class="layadmin-tabspage-none"></div>
</div>
class Router{
    constructor(options){
        //缓存route数据信息
        this.routes = {};
        this.options = options;
        this.ready();
    }

    //伪数组转为真数值
    static arrayLike(arrLike){
        return Array.from ? Array.from(arrLike) : Array.prototype.slice.call(arrLike);
    }

    static isLikeArr(el){
        return typeof el == 'object' && !(el instanceof Array) && el.length>0 ? true : false;
    }

    static isDOM(el){
        return el.nodeType == (Node.ELEMENT_NODE||Node.DOCUMENT_NODE) || Router.isLikeArr(el);
    }

    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 animationEnd(ele,sucHandle){
        //1、获取动画名
        let animateName = function(){
            const animation = {
                'animation': 'animationend',
                'OAnimation': 'oAnimationEnd',
                'MozAnimation': 'mozAnimationEnd',
                'WebkitAnimation': 'webkitAnimationEnd'
            }
            const animateName = (function(el) {
                for (let t in animation) {
                    if (el.style[t] !== undefined) {
                        return animation[t];
                    }
                }
            })(document.createElement('div'));
            return animateName;
        }();
        //2、给ele绑定动画结束的回调
        const animateEndEventListener = function(sucHandle){
            //在每次transitionEnd的事件后执行该函数
            const handleAniEnd = function(e){
                ele.removeEventListener(animateName,handleAniEnd);
                sucHandle.call(this,e,ele);
            };
            ele.addEventListener(animateName,handleAniEnd,false);
        }
        animateName && animateEndEventListener(sucHandle)
    }

    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 isHash(val){
        return /#[^#.]+/.test(val)
    }

    static evalScripts(text){
        let script
        ,scripts = []
        , regexp = /<script[^>]*>\s*([\s\S]*?)\s*<\/script>/gi;
        while(script = regexp.exec(text)){
            scripts.push(script[1])
        }
        scripts = scripts.join('\n');
        //window.execScript只有ie有
        scripts && (!window.execScript ? eval(scripts) : execScript(scripts))
    }

    static setTitle(htmlString){
        let result = /<title>([\s\S]*?)<\/title>/.exec(htmlString) 
        ,title = result ? result[1] : htmlString;
        document.querySelectorAll('title')[0].textContent = title
    }

    parse(text){
        Router.setTitle(text)
        document.querySelector(this.options.routerView).innerHTML = text;
        Router.evalScripts(text)
    }

    //收集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();
    }
}


//使用方式:

       let router = new Router({
                routerView:'#app-body'
            })
            //1、注册routes依赖
            router.route("#/home",function(){
                router.parse("hello home page !!")
            })
            router.route("#/button",function(){
                $.ajax({url:'./component/button.html'}).then(function(html){
                    router.parse(html);
                })
            })
            router.route("#/bdage",function(){
                $.ajax({url:'./component/bdage.html'}).then(function(html){
                    router.parse(html);
                })
            })
            router.route("#/form",function(){
                $.ajax({url:'./component/element.html'}).then(function(html){
                    router.parse(html);
                })
            })

            $.ajax({url:'./view/layout.html'}).then(function(html){
                document.querySelector("#app").innerHTML = html;
                //2、初始化默认页
                router.init('#/home')
                Router.evtListener(document.querySelectorAll('[r-link]'),'click',function (e) {
                    router.redirect(this.getAttribute('r-link'))
                })
            })
posted @ 2020-09-03 13:19  littleboyck  阅读(553)  评论(0编辑  收藏  举报