type
Post
status
Published
date
May 11, 2020
slug
summary
window.history 与 history 库的介绍
tags
Web dev
ReactJS
category
技术分享
icon
password

抛砖引玉

  1. window.location | window.history | history 库 | react-router | react-router-redux(connected-react-router)
  1. history.listen 什么时候触发?变化时触发?我调用history.replace(),但是 location 参数没变化会触发吗?
  1. dispatch(routerRedux.push(…)) 为什么要这样写?history.push(…)可以吗?routerRedux 我们用对了吗?
  1. 搞这么多 API 真复杂,使用浏览器原生 API 解析 url 和跳转,不香吗?香,但要避免踩坑(兼容:浏览器的兼容、hashHistory 和 browserHistory 的兼容)

浏览器 API

location

小结:
  1. window.location 与 location 是一个东西,甚至与 window.document.location 和 document.location 都是一个东西
  1. 掌握读写操作,读 - 知道字段含义,写 - 知道方法区别
    1. ancestorOrigins: DOMStringList {length: 0} assign: ƒ assign() fragmentDirective: FragmentDirective {} hash: "#components-table-demo-virtual-list" host: "ant.design" hostname: "ant.design" href: "https://ant.design/components/table-cn/?useless=1&test=2#components-table-demo-virtual-list" origin: "https://ant.design" pathname: "/components/table-cn/" port: "" protocol: "https:" reload: ƒ reload() replace: ƒ replace() search: "?useless=1&test=2" toString: ƒ toString() valueOf: ƒ valueOf() Symbol(Symbol.toPrimitive): undefined __proto__: Location
  1. location.origin 会有老版浏览器兼容问题

window.history

window.history、history 一个东西
为了与 history 库区分,以下都叫 window.history
小结:
  1. 出于隐私考虑,不会获取到详细的浏览历史
  1. window.history.pushStatewindow.history.replaceState:相同之处是两个 API 都会操作浏览器的历史记录,而不会引起页面的刷新;不同之处在于,pushState会增加一条新的历史记录,而replaceState则会替换当前的历史记录。

前端路由解决方案

什么叫前端路由:改变 URL,不会请求后端(不刷新),但是页面内容会发生变化
那么有哪些情况改变 URL,不会请求后端:
  1. hash 变化(无论使用js、还是在地址栏输入),不会请求后端
  1. window.history.pushState()
怎么让页面内容变化:
就是要让 js 知道 url 变化了,怎么搞?
  1. 对于方案 1 window.addEventListener('hashchange', ...)
  1. 对于方案 2 window.addEventListener('popstate', ...)

history 库

它封装了上面两种方案,统一了浏览器差异
小结:
  1. 改变 URL,不会请求后端
    1. history.push(path, [state]); history.replace(path, [state]); history.go(n); history.goBack(); history.goForward();
  1. 让 js 知道 url 变化了
    1. history.listen((location, action) => ...),这里的 location 可不是 window.location,但是对字段使用了相同的命名 { pathname, search, hash, state },你一定记得 history@2.x 有个 query 参数,在 history@3.x 中可以通过使用 useQueries 参数,让 location 有 query 参数,但在 history@4.x 完全取消了 query,为的是保证 history.location 是 window.location 的严格子集
  1. 你可能不知道
    1. const history = createHistory({ basename: '/the/base' });
  1. 你可能不知道
    1. // Register a simple prompt message that will be shown the // user before they navigate away from the current page. const unblock = history.block('Are you sure you want to leave this page?'); // Or use a function that returns the message when it's needed. history.block((location, action) => { // The location and action arguments indicate the location // we're transitioning to and how we're getting there. // A common use case is to prevent the user from leaving the // page if there's a form they haven't submitted yet. if (input.value !== '') return 'Are you sure you want to leave this page?'; }); // To stop blocking transitions, call the function returned from block(). unblock();
  1. browserHistory 需要服务端做什么?把所有请求(或视情况而定)转发到 index.html 举一个实际的例子,现在的前端 nginx,只做了域名和静态资源简单的映射 如:只做了 https://zyh.group.com/ -> https://static.group.com/zyh/index.html
    1. 需要如下配置
      location / { try_files $uri /index.html; }
      也可以 node 做,谁都可以做

react-router

  1. 注意大版本升级的 breaking changes,印象中 @2.x 升 @3.x 和 @3.x 升 @4.x 时,网上都是一片哀嚎,据说 @4.x 升 @5.x 很平稳
  1. @4.x 是有一波大的重构,有了<Switch />,一开始还不明白这是干嘛的,其实就如同 js 中的 switch, 依次匹配,匹配成功则停止,是为了防止 url 匹配到多个符合条件的路由
  1. <Link /> 组件和 <a /> 标签一样吗?
  1. 官方说的 react-router-redux 已经不支持 react-router@4.x 了

react-router-redux

同步 router 和 redux
小结:
  1. 为什么不维护?很多依赖的 react api 即将废弃,需要一波重构,结果社区已经有人搞好了。用的时候也会看到很多 warning,并且放到 react-router 中维护了,但是只维护 @4.x,@5.x 以上可以看到都删掉了,之后得改用 connected-react-router,dva 最新的代码中都改了
    1. notion image
  1. 都已经不维护了,才发现之前根本没用对

connected-react-router

小结:
  1. 用 hooks api 做了重构,用法和 react-router-redux 差不多

回到开始的问题

  1. 看源码实现
  1. routerRedux.push(...) 返回的是 action,所以要 dispatchhistory.push(...) 其实可以满足相同的需求。 区别是前者需要注入 dispatch,使用 connect 注入;后者需要注入 history,要么 react-router 已注入,要么使用 withRouter
    1. 在 model 中跳转需使用前者
  1. 小心下面情况
    1. // "https://zyh.group.com/#/list?key=1&value=2" console.log(window.location) // ... hash: "#/list?key=1&value=2" search: "" // ...
      // "https://zyh.group.com/list?key=1&value=2#hash" // ... hash: "#hash" search: "?key=1&value=2" // ...
       
【译】无线局域网中采用组播模式的低速率DoS攻击性能评估Dva Effects 进阶