hash、history路由

在Web前端单页应用SPA(Single Page Application)中,路由描述的是URL与UI之间的映射关系,这种映射是单向的,即URL变化引起UI更新(无需以及不会刷新页面)

与window.location有关的api
	http://www.joymood.cn:8080/test.php?user=admin&pwd=admin#login
	
	location.href:得到整个如上的完整url
	location.protocol:得到传输协议http:
	location.host:得到主机名连同端口www.joymood.cn:8080
	location.hostname:得到主机名www.joymood.cn
	location.pathname:得到主机后部分不包括问号?后部分的/test.php
	location.search:得到url中问号?之后井号#之前的部分?user=admin&pwd=admin
	location.hash:得到#之前的部分#login

具体应用:
	Vue等前端路由的实现
	
	组件功能:
		页面上监听浏览器前进后退操作,使得类似左侧点击列表,回退到上一个选中的列表,而非回退页面

弊端:
	hash路由:https://music.163.com/#/playList?id=123456 
		因为只是改锚点#的内容,所以调用浏览器刷新时,不会丢失页面
	history路由:https://music.163.com/playList?id=123456 
		因为改变的url是自定义的,并不是服务器上真实存在的路径,所以调用浏览器刷新时,页面会报404的错误

hash路由
	hash是URL中hash(#)及后面的那部分,常用作锚点在页面内进行导航,改变URL中的hash部分不会引起页面刷新
	通过hashchange事件监听URL的变化,改变URL的方式只有这几种:
	(1)通过浏览器前进后退改变URL
	(2)通过<a>标签改变URL
	(3)通过window.location改变URL
	(4)即使在hash模式下,依旧可以使用history.go,back,forward等触发hashchange事件,因为浏览器保存记录都是同一个栈
	

history路由
	history提供了pushState和replaceState两个方法,这两个方法改变URL的path部分不会引起页面刷新
	
	(1)history对象	
		history.state		存入浏览器记录中的值
		
		history.back()
		history.forward()
		history.go(n)		去到指定记录,不填重新加载当前页
		
		往浏览器中添加一条记录,在回退前进时会返回这些记录
		history.pushState(放入浏览器的任意存储值,标题但浏览器都不支持null即可,'放在域名后的路径')
		
		替换当前记录,类似重定向
		history.replaceState(放入浏览器的任意存储值,标题但浏览器都不支持null即可,'放在域名后的路径')
		
	(2)通过浏览器前进后退改变URL时会触发popstate事件
				
		window.addEventListener('popstate',function(){
			history.state 取得当前浏览器对象存储的值
		})
		
		不能监听的情况:
			通过pushState/replaceState或<a>标签改变URL不会触发popstate事件
		
		能监听的情况:
			通过浏览器前进后退改变URL
			history的back、go、forward方法
			window.location

 	(3)对不能监听情况的处理
 		(1)拦截pushState/replaceState,即重写方法
 		
			var _wr = function(type) {
			  var orig = history[type];
			  return function() {
			    var e = new Event(type);
			    e.arguments = arguments;
			    window.dispatchEvent(e);
			    // 注意事件监听在url变更方法调用之前 也就是在事件监听的回调函数中获取的页面链接为跳转前的链接
			    var rv = orig.apply(this, arguments);
			    return rv;
			  };
			};
			history.pushState = _wr('pushState');
			history.replaceState = _wr('replaceState');
			
			window.addEventListener('pushState', function(e) {
			  var path = e && e.arguments.length > 2 && e.arguments[2];
			  var url = /^http/.test(path) ? path : (location.protocol + '//' + location.host + path);
			  console.log('old:'+location.href,'new:'+url);
			});
			window.addEventListener('replaceState', function(e) {
			  var path = e && e.arguments.length > 2 && e.arguments[2];
			  var url = /^http/.test(path) ? path : (location.protocol + '//' + location.host + path);
			  console.log('old:'+location.href,'new:'+url);
			});
			
		(2)劫持a标签的点击事件
			event.preventDefault()

代码示例:

    <div>
        <button class="btn" onclick="btnFun();">点击新增一条历史记录</button>
    </div>

    <div>
        <button class="btn" onclick="btnFun2();">点击新增一条历史记录2</button>
    </div>
    
    
    <!-- <script src='https://res.wx.qq.com/open/js/jweixin-1.3.2.js'></script> -->
    <!-- <script src="./1.js"></script> -->
    <script>
        console.log('增加历史记录前 state的值:',history.state); 
        function btnFun() {
    
    

            history.pushState('a',null,'index2.html?a=2');
            console.log('增加历史记录后 state的值:',history.state); 
        

            // history.replaceState('b',null,'index3.html?b=2');
            // console.log('增加历史记录后 state的值:',history.state); 
        };

        function btnFun2() {
    
    

            history.replaceState('c',null,'index4.html?c=2');
            console.log('增加历史记录后 state的值:',history.state); 


        };
        
        window.addEventListener('popstate',function() {
    
    
            var state = history.state;
            console.log(history)
            console.log('点击后退按钮后 state的值:',state); 
   
        });

    </script>

猜你喜欢

转载自blog.csdn.net/weixin_43294560/article/details/121855085