后端路由: 后端服务器根据 url 地址找到对应的html文件,然后把该页面文件发送给浏览器。
前端路由spa: url变化,更新页面组件,但不希望向服务器发送url资源请求

两种方式: hash、history

hash:

window.location.hash    # 取值或赋值
window.onhashchange()    # 监听变化

改变hash的方式:

  • 浏览器地址栏手动更改
  • location.hash=
  • a标签锚定指定name的a, 或指定id的任意标签

都反映在浏览器url上,都更改location.hash值,且都触发hashchange

hash模式需要注意:

  • hash值不会随http请求发送到服务器
  • 只修改浏览器的hash部分,按下回车,浏览器不会发送任何请求给服务器,只会触发hashchange事件并且修改location.hash的值
  • hash模式下,手动刷新页面不会向浏览器发送请求,不会触发hashchange事件,但是会触发window.onload事件
  • hash写入时,会在不重载网页的前提下,创造一条访问历史记录,使用"后退"按钮,就可以回到上一个位置。上述规则对IE 6和IE 7不成立,它们不会因为#的改变而增加历史记录。

history:

history.pushState(stateObj,title,url)
history.replaceState(stateObj,title,url)

history.back()、forward()、go()
window.onpopstate()
history.state # 堆栈最上层的状态值,当前历史记录的状态对象

history模式需要注意:

  • pushState会增加一条新的历史记录,而replaceState则会替换当前的历史记录,两个 API 都会操作浏览器的历史记录,而不会引起页面的刷新。
  • 浏览器的前进与后退(按钮、back、forward、go ),会触发window.onpopstate事件。
  • 超出栈的go back不会触发 onpopstate
  • state对象最大640k,否则异常
  • popstate事件的回调函数中获取当前的历史记录的状态对象的拷贝。但是,这两个对象并不相同,简单的说e.state是history.state的深拷贝。

两种模式的差异 & 需要注意:

  1. hash 模式只可以更改 # 后面的内容,因此只能设置与当前 URL 同文档的 URL;
    History 模式可以通过pushState() API 设置任意的同源 URL;
  2. hash 设置的新值必须与原来不一样才会触发动作将记录添加到栈中;Hash模式下, 多次刷新为同一个页面的话,记录只添加一次;
    history.pushState() 设置的新 URL 可以与当前 URL 一模一样,这样也会把记录添加到栈中;
  3. hash 模式只能更改哈希值,也就是字符串;
    History 模式可以通过pushState() stateObject 参数可以添加任意类型的数据到记录中;
  4. pushState() 可额外设置 title 属性供后续使用,目前没有用。

当然啦,history 也不是样样都好。SPA 虽然在浏览器里游刃有余,但真要通过 URL 向后端发起 HTTP 请求时,两者的差异就来了。尤其在用户手动输入 URL 后回车,或者刷新(重启)浏览器的时候。

  • hash 模式下,仅 hash 符号之前的内容会被包含在请求中, 模式无需后端配置,并且兼容性好。
  • history 模式,前端的 URL 必须和实际向后端发起请求的 URL 一致,如果后端缺少对 /book/id 的路由处理,将返回 404 错误。后端需要配置 index.html 页面用于匹配不到静态资源的时候,或者开启NGINX配置

hashchange、popstate触发条件:

同时触发

loaction.hash = ‘’

都不触发,即使当pushState函数设置url参数的值为hash格式时,也不会触发hashchange事件

history.pushstate({},'','history’)
history.replacestate({},'','history’)

触发popstate,有hash改变会触发hashchange

 按钮、history.go、back、forward

注意事项:超出栈的go back不会触发 popstate


mayihetu
107 声望3 粉丝