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路由

hash是URL中hash(#)及后面的那部分,常用作锚点在页面内进行导航,监听 window 的 hashchange 事件,当散列值改变时,可以通过 location.hash 来获取和设置hash值

//设置 url 的 hash,会在当前url后加上'#abc'
window.location.hash='abc';
let hash = window.location.hash //'#abc'

window.addEventListener('hashchange',function(){
	//监听hash变化,点击浏览器的前进后退会触发
})
  • 通过hashchange事件监听URL的变化

  • 能监听的情况
    • 通过浏览器前进后退改变URL
    • 浏览器输入URL中hash变化
    • 通过<a>标签改变URL
      • <a>标签的属性 href 可以设置为页面的元素ID如 #top,当点击该链接时页面跳转至该id元素所在区域,同时浏览器自动设置 window.location.hash 属性,地址栏中的哈希值也会发生改变,并触发onhashchange事件
    • 通过window.location改变URL
    • 即使在hash模式下,依旧可以使用history.go,back,forward等触发hashchange事件,因为浏览器保存记录都是同一个栈
  • 优点

    • 改变URL中的hash部分不会引起页面刷新,散列值是不会随请求发送到服务器端的,所以改变hash,不会重新加载页面
  • 弊端

    • SEO不行

history路由

history提供了pushState和replaceState两个方法,这两个方法改变URL的path部分不会引起页面刷新

  • history API

history.state		存入浏览器记录中堆顶的值
history.length		当前窗口访问过的网址数量(包括当前网页)

history.back()
history.forward()
history.go(n)		去到指定记录,不填或0刷新当前页

往浏览器中添加一条记录,在回退前进时会返回这些记录
history.pushState(放入浏览器的任意存储值,标题但浏览器都不支持''即可,'放在域名后的路径')

替换当前记录,类似重定向
history.replaceState(放入浏览器的任意存储值,标题但浏览器都不支持''即可,'放在域名后的路径')
  • 监听URL变化

// 每当 history 对象出现变化时,就会触发 popstate 事件。
window.addEventListener('popstate',function(event){
	history.state||event.state 取得当前浏览器对象存储的值
})
  • 不能监听的情况:

    • 通过pushState/replaceState或<a>标签改变URL不会触发popstate事件
    • 该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。
    • 页面第一次加载的时候,浏览器不会触发popstate事件
  • 能监听的情况:

    • 通过浏览器前进后退改变URL
    • history的back、go、forward方法
    • window.location
  • 对不能监听情况的处理

    • 劫持a标签的点击事件:event.preventDefault()
    • 拦截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;
  };
};
// 重写自定义方法,内部通过window.dispatchEvent(e)调用自定义监听
history.pushState = _wr('pushState');
history.replaceState = _wr('replaceState');

// 自定义监听pushState、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);
});
  • 弊端

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

代码示例:

    <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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值