原生js实现一个hash路由


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

目录所在位置:router文件夹

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

 
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 = /]*>\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 = /([\s\S]*?)<\/title>/<span style="color: rgba(0, 0, 0, 1)">.exec(htmlString) 
        ,title </span>= result ? result[1<span style="color: rgba(0, 0, 0, 1)">] : htmlString;
        document.querySelectorAll(</span>'title')[0].textContent =<span style="color: rgba(0, 0, 0, 1)"> title
    }

    parse(text){
        Router.setTitle(text)
        document.querySelector(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.options.routerView).innerHTML =<span style="color: rgba(0, 0, 0, 1)"> text;
        Router.evalScripts(text)
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">收集routes</span>
<span style="color: rgba(0, 0, 0, 1)">    route(path,callback){
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.routes[path] = callback ? callback : <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){};
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">重定向会改变hash</span>
<span style="color: rgba(0, 0, 0, 1)">    redirect(path){
        location.hash </span>!= path && (location.hash =<span style="color: rgba(0, 0, 0, 1)"> path)
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">跳转是内部行为,不改变hash</span>
<span style="color: rgba(0, 0, 0, 1)">    forward(path){
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.routes[path] && <span style="color: rgba(0, 0, 255, 1)">this</span>.routes[path].call(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">)
    }

    init(firstPath){
        let curHash </span>=<span style="color: rgba(0, 0, 0, 1)"> location.hash;
        curHash </span>&& (firstPath =<span style="color: rgba(0, 0, 0, 1)"> curHash)
        Router.isHash(firstPath) </span>&& (location.hash = firstPath) && curHash && <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.forward(firstPath)
    }
    
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">监听hashchange</span>
<span style="color: rgba(0, 0, 0, 1)">    listenerHashchange(){
        Router.evtListener(window,</span>'hashchange',()=><span style="color: rgba(0, 0, 0, 1)">{
            </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.forward(location.hash)
        });
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">初始化</span>
<span style="color: rgba(0, 0, 0, 1)">    ready(){
        </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.listenerHashchange();
    }
}<br><br><br>//使用方式:<br><br></span></pre>

       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);
                })
            })
<br>
            $.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'))
                })
            })
						  
					  </div>
						<!--conend-->
							<div class="p-2"></div>

						<div class="arcinfo my-3 fs-7 text-center">
							
							
			<a href='/t/etagid59326-0.html' class='tagbtn' target='_blank'>hashrouter</a><a href='/t/etagid11119-0.html' class='tagbtn' target='_blank'>router</a><a href='/t/etagid11117-0.html' class='tagbtn' target='_blank'>路由</a>							
						



						</div>
						
						<div class="p-2"></div>

						

						
					</div>
					<div class="p-2"></div>
					<!--xg-->
					<div class="lbox p-4 shadow-sm rounded-3">
						<div class="boxtitle"><h2 class="fs-4">相关</h2></div>
						
<hr>				
						
			<div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-565333.html">Django  url路由分配</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-563440.html">openstack分布式路由详解</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-562530.html">ceryx+redis实现nginx动态路由功能、动态管理upstream</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-561824.html">AntDesign vue学习笔记(三)嵌套路由使用</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-553865.html">vue-router history模式在nginx二级目录下的配置</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-553354.html">47-this.$route.和this.$router的区别</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-552793.html">前端MVC学习总结(三)——AngularJS服务、路由、内置API、jQueryLite</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-550354.html">路由器的配置</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-546593.html">vue指定返回键的路由(点击浏览器的返回按钮/beforeRouterLeave)</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-539113.html">Flask 蓝图进行路由分发</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-539131.html">.Net Mvc 4 Route路由</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div><div class="row g-0 py-2 border-bottom align-items-center">
																
								<div class="col-7 col-lg-11 border-lg-end">
										<h3 class="fs-6 mb-0 mb-lg-2"><a href="/a/1-538465.html">前端路由</a></h3>
									
									<div class="ltag fs-8 d-none d-lg-block">
								 

        </div>
								</div>
							
							</div>            
            
            <!---->
                                    
           <!---->
  			
						

					</div>
					<!--xgend-->
				</div>

				<div class="col-lg-3 col-12 p-0 ps-lg-2">
					<!--box-->									
					<!--boxend-->
					<!--<div class="p-2"></div>-->

					<!--box-->
									<div class="lbox p-4 shadow-sm rounded-3">
					
									   <div class="boxtitle pb-2"><h2 class="fs-4"><a href="#">标签</a></h2></div>
										<div class="clearfix"></div>
										<ul class="m-0 p-0 fs-7 r-tag">
										</ul>
									

										
										<div class="clearfix"></div>
									</div>
					<!--box end-->

					
				</div>

			</div>
		
		
		
		</div>	

</main>
						<div class="p-2"></div>
<footer>
<div class="container-fluid p-0 bg-black">
	<div class="container p-0  fs-8">
	<p class="text-center m-0 py-2 text-white-50">一品网 <a class="text-white-50" href="https://beian.miit.gov.cn/" target="_blank">冀ICP备14022925号-6</a></p>
	</div>	
</div>
<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?6e3dd49b5f14d985cc4c6bdb9248f52b";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>
</footer>
		
<script src="/skin/bootstrap.bundle.js"></script>

</body>
</html>