选择主题

选择导航背景

history和hash路由

面试官:你用vue开发,那vue-router是怎么实现页面跳转的
我脱口而出,我用history……
事后想想,地址栏这么大一个#在那里,我在睁眼说什么瞎话……面试官怕不是已经扶额了……


来记录一下hash和history的区别和一些小点吧

1.history
介绍history的文章已经很多了,本身history不算太复杂,主要有以下几个东西
(1)window.history.pushState(obj, title [, url])
(2)window.history.replaceState(obj, title [, url])(3)一个popstate事件,在前进和后退调用时触发

来段代码

复制代码

<body>
  <p>随机生成的数字是: <span id="num"></span></p>
  <button onclick="random()">随机生成</button>
  <script>
    function random () {      var num = parseInt(Math.random() * 100)
      document.getElementById('num').innerHTML = num
      window.history.pushState({num: num},'', num);
    }
    window.addEventListener('popstate', function (e) {
      console.log('active')
      document.getElementById('num').innerHTML = e.state.num
    })  </script>

复制代码

但是,直接用是不行的,如果你把这个html文件直接在浏览器里打开,按几下按钮,会出现

Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'file:///E:/buildDisplay/4' cannot be created in a document with origin 'null' and URL

 

其实这个错只是让你跑个服务器而已,简单的nodejs写一个就好了,这不是重点

复制代码

var express = require('express')var app = express()var path = require('path');var router = express.Router()
app.get('/testHistory', function (req, res) {
  res.sendFile(path.join(__dirname, './test.html'))
})
app.listen(5001, function (data) {
  console.log('server listened at 5001')
})

复制代码

 

 

效果,没有问题

注意:

<1>这样改变url,并不会向后台发送请求,后退也不会

<2>但是,一旦刷新了,那真的去请求了,而后台往往没有这个路由,然后就404了

 

所以,在vue-router使用history模式的时候,有这样一句提示

当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!

不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。

所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

 

2.hash

hash相比history,稍微丑了点,带个#,因为服务器不会管#后面的内容(根本不会发给服务器),所以不存在404的问题

hash主要就是一个事件,hashchange,直接上demo就好

复制代码

<body>
  <p>随机生成的数字是: <span id="num"></span></p>
  <button onclick="random()">随机生成</button>
  <script>
    function random () {      var num = parseInt(Math.random() * 100)
      document.getElementById('num').innerHTML = num
      window.location.hash = "num=" + num
    }
    window.addEventListener('hashchange', function (e) {      var str = e.newURL.split('#')[1]
      document.getElementById('num').innerHTML = str.split('=')[1]
    })  </script>

复制代码

 

以上是前端实现路由的常见的2种方式