彻底弄懂vue两种路由(hash与history)的原理,包括路径改变页面刷新与不刷新,如何与路径联系切换组件的,以及为什么history模式会有点小问题(发请求到后端404这种)

代码1

锚点测试

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <!-- 方式一 -->
  <!-- <a href="#go">a</a>
  <h1 style="height: 2000px;display: flex;background-color: red;align-items: flex-end;">
    <div id="go">锚点实现</div>
  </h1> -->
  <!-- 方式二 name 但name要加在a标签上,实际使跳到另一个a标签那儿 -->
  <!-- <a href="#go">a</a>
  <h1 style="height: 2000px;display: flex;background-color: red;align-items: flex-end;">
    <a name="go">锚点实现</a>
  </h1> -->
  <!--  方式三 使用scrollIntoView方法 -->
  <!-- =--------重点!!!有时候一个方法它本身没有,要注意往它原型链上找啊。。。。 -->
  <h1 id="h110" style="width: 2000px;height: 2000px;display: flex;background-color: red;align-items: flex-end;">
    <a name="go"
      onclick="javascript:document.getElementById('h110').scrollIntoView({behavior: `smooth`, block: `start`, inline: `end`})">锚点实现</a>
  </h1>
  <!-- 方式4 用js动态把元素的offsettop赋值scrolltop -->
  <!-- https://www.cnblogs.com/huihuihero/p/14210230.html -->
  <!-- 这种锚点跳转,简单的定位层级结构可以用,但是比较复杂的定位嵌套可能就得递归得到所有的offsettop相加了 -->
</body>

</html>

代码二,offset测试研究

<!-- 如果没有这句话 就得不到document.docuementElement -->
<!-- 只能得到document.body -->
<!DOCTYPE html>

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .box1 {
      width: 400px;
      height: 400px;
      border: 1px solid blue;
      position: relative;
      top: 200px;
    }

    .box2 {
      width: 300px;
      height: 300px;
      border: 1px solid red;
      position: relative;
      top: 20px;
    }

    .box3 {
      width: 200px;
      height: 200px;
      border: 1px solid pink;
      position: absolute;
      top: 60px;
    }
  </style>
</head>

<body>
  <div class="box1">
    <div class="box2">
      <div class="box3"></div>
    </div>
    <div class="box2">
      <div class="box3"></div>
    </div>
    <div id="shit" class="box2">
      <div class="box3"></div>
    </div>
  </div>
  <script>
    let box1 = document.querySelector('.box1')
    let box2 = document.querySelector('.box2')
    let box3 = document.querySelector('.box3')
    let shit = document.getElementById('shit')

    console.dir(box1)
    console.dir(box2)
    console.dir(box3)
    console.dir(shit)
    // offsetTop是当前元素距离其上一层定位元素的距离
    // 它只看结果,不看过程
    // 也就是自然上下或左右块级排列或者定位移动
    // 不管你怎么弄了,它一定帮你得到离其上一层定位元素的距离
  </script>
</body>

</html>

代码三四,vue路由原理研究

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="go">go</div>
  <!-- <a href="1.html#tabl1">tab1</a> -->
  <a href="1.html#tabl1">tab1</a>
  <div onclick="fuck()">返回</div>
  <script>
    // vue路由hash和history切换页面不刷新原理
    // hash用的是#  histoty用的是hisoty.pushstate()
    // vue路由跳转页面是没有刷新的
    // 它有两种路由方式 1种是#sfads 这是#hash的方式
    // #后面的东西就可以随意写 不会触发页面刷新 然后配合hashchange事件
    // 然后可以拿到两次hash变化的比较,再与router数组比较
    // 得到需要展示的组件,替换router-view
    // 第二种 利用history
    let a = document.querySelector('#go')
    a.addEventListener('click', () => {
      // 这里试验得出如果增加 / 那么就会跳转找这个页面
      // 但是加#号并不会跳转 #后面的东西就可以随意写 这也是vue hash路由的实现原理
      // window.location.href = 'http://127.0.0.1:5500/%E8%B7%AF%E7%94%B1%E7%9A%84%E7%A0%94%E7%A9%B6/2.html'
      // window.location.href = 'http://127.0.0.1:5500/%E8%B7%AF%E7%94%B1%E7%9A%84%E7%A0%94%E7%A9%B6/1.html#abc'
      // window.location.href = 'http://127.0.0.1:5500/%E8%B7%AF%E7%94%B1%E7%9A%84%E7%A0%94%E7%A9%B6/1.html#/15/16'

      // 替换整个,页面会刷新,也就是左上角会转
      // window.location.reload()
      // alert(`${location.protocol},\n
      // ${location.host},\n${location.hostname}
      // \n,${location.port},${location.pathname}`)
      // 只替换pathname,还是刷新页面了
      // location.pathname = '/%E8%B7%AF%E7%94%B1%E7%9A%84%E7%A0%94%E7%A9%B6/2.html'
      // location.pathname = '/%E8%B7%AF%E7%94%B1%E7%9A%84%E7%A0%94%E7%A9%B6/1.html#111'
      // 页面没有刷新
      // location.href = '1.html#tabl1'
      // 没替换掉
      // window.history.go('http://127.0.0.1:5500/%E8%B7%AF%E7%94%B1%E7%9A%84%E7%A0%94%E7%A9%B6/1.html#/15/16')
      const state = { 'page_id': 1, 'user_id': 5 }
      const title = ''
      const url = 'hello-world.html'

      history.pushState(state, title, url)
      // 我监听这个点击事件??然后拿到
      console.log('historystate', history.state)
    })
    // 。。。。hashchange只能监听到有 # 的变化
    // 也就是history这种没有#的不会触发这个
    window.addEventListener('hashchange', (e) => {
      console.log('e', e)
    })
    window.addEventListener('popstate', (e) => {
      console.log('eee', e)
    })


    // ----地址栏回车的时候,那个请求是在network 点Doc那里可以看
    // 可以去看看hash和history这两种,为什么history发请求会有问题
    // 因为hash #后面的都不会带到请求里 也就是相当于每次都请求的服务器的那个index.html
    // 但是history全带进去了,这样 后台对应不上,不就404找不到请求或者页面了吗
    // 不明白的点是,地址栏那里是会发请求是把  --已经明白了
    // 是的 打开network 点Doc 那里会发请求s
    // 当然了,如果你是hash的话,也就是#/asdfasd这种
    // 那么除非你在地址栏点一下,然后回车,不管地址变没变一定会发请求
    // 不然你点页面里的路由切换,造成地址栏变化不会发请求

    // 这里我要说几点
    // 1.只有点地址栏然后回车,或者点左上角的刷新或者location.reload
    // 或者window.location.href替换的地址不是除了#号后面部分其他没变
    // 那么页面才会刷新,打开network 点Doc 那里会发请求可以看到

    // 2.vue的hash和history路由都不会造成页面刷新
    // hash我能理解不会造成页面刷新,毕竟在#号后面
    // 但是history切换为什么也没造成页面刷新呢
    // 是怎么做到的
    // 试了一下,使用pushState实现了
    // 但是这个只是实现了改变地址栏,页面不刷新
    // 它是怎么动态监测到地址栏变化的
    // hash的话是通过hashchange
    // 但是history方式由于没有#了,所以不会触发hashchange了
    // 那么是怎么动态监测的地址栏变化的呢

    // -------重点   hash和history路径与组件能够联系起来,切换组件的原理
    // 我搞明白了
    // 首先hash和history两种路由,其实在vue中要实现出根据路径变换组件,他们都有两个思路
    // 一个是根据地址栏变化,拿到变化前后的路径进行比较,hashchange中能拿到,然后据此得到
    // 新增的那个路径字符串,再和router数组比较,得到相应组件替换router-view来渲染
    // 这种方式的话,不管是手动$router.push的或者router-link的,或者直接改变地址栏,回车刷新
    // 都能检测到变化,因为有hashchange事件
    // 这种对于hash模式是没有问题,可行的
    // 但是对于history模式不行
    // 因为hashchange事件,包括popstate,对于history.pushstate都是检测不到的
    // 所以history模式也就没法用这个思路来实现了

    // 那么第二种方式是什么呢,第二种方式则是如此
    // $手动$router.push的或者router-link的这些,他们写的时候就带着相应的路由参数
    // 根据这个先和router数组比较,得到相应组件替换router-view来渲染,然后再去改地址栏
    // 就不用监测不监测的了
    // 那么对于直接改变地址栏,回车刷新以及左上角刷新等刷新页面的操作
    // 检测不到路径变化又该怎么去对比着拿到路径,渲染相应组件呢
    // 其实,你应该仔细想想,既然都已经重新刷新了
    // 那么类似于初始化了,从入口函数开始重新执行了所有代码
    // 那么你难道不可以在入口哪儿写一下,拿到当前路径,和router数组比较,得到相应组件替换router-view来渲染吗
    // 然后后续的路由变化不都是手动的吗,手动的就可以第二种,而一旦页面刷新这种的,
    // 不就可以初始化的时候弄吗,
    // 这不就都解决了吗,事实上,第二种也比第一种好,第一种还得字符串比较
    // 有必要吗,搞这么麻烦,第二种直接vue,按规范写$router.push的或者router-link,去比去渲染就行
    // 之后再改页面

    // 参数资料
    https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState
    https://segmentfault.com/q/1010000022204297
    https://www.jianshu.com/p/557f2ba86892
    https://www.w3school.com.cn/jsref/met_his_forward.asp
    https://www.cnblogs.com/Yirannnnnn/articles/5002983.html
    https://www.w3cplus.com/html5/html5-history-api.html
    https://www.jianshu.com/p/4295aec31302
    https://www.runoob.com/js/js-window-location.html


    // hash它是通过 window.location.href或者a标签的href标签来改变
    // 地址的,并且放在#后面  #号后面的不会造成页面刷新
    // 那么history没有#,window.location.href或者a标签的href标签来改变
    // 这两种方式显然是不行的了,因为没再#后面会造成页面刷新

    function fuck() {
      window.history.go(-1)
    }


    // debug思路
    // 可以别到处console。log
    // 而是在相应的地方写上debugger,然后进去,f8是跳到下一个debugger或者直接点
    // 那个播放也是下一个debugger
    // 然后就可以看相应的值是多少,这样效率要高一些
    // 还有一点就是,debugger的时候
    // debugger的那部分代码
    // 会形成作用域
    // 也就是说,你此时可以在console控制台中查看或者修改这些值
    // 比如里面有个res。code 本来是等于200的
    // 你可以直接在console中写res.code=300,然后你会发现变成300了
    // 然后你继续执行,这个的好处是有一些操作流程很复杂的debugger
    // 往往只需要看某一个部分的执行结果,所以这样修改就可以在这里改一次,改一下,改成想要验证的数据
    // 验证结果

  </script>
</body>

</html>

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  sdgdf
</body>

</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值