browserHistory和hashHistory
首先 browserHistory 其实使用的是 HTML5 的 History API,浏览器提供相应的接口来修改浏览器的历史记录,不少方法还是实验性的,而且 E10 以下不支持;而 hashHistory 是通过改变地址后面的 hash 来改变浏览器的历史记录;
History API 提供了 pushState() 和 replaceState() 方法来增加或替换历史记录。而 hash 没有相应的方法,所以并没有替换历史记录的功能。但 react-router 通过 polyfill 实现了此功能,具体实现没有看,好像是使用 sessionStorage。
另一个原因是 hash 部分并不会被浏览器发送到服务端,也就是说不管是请求 #foo 还是 #bar ,服务只知道请求了 index.html 并不知道 hash 部分的细节。而 History API 需要服务端支持,这样服务端能获取请求细节。
还有一个原因是因为有些应该会忽略 URL 中的 hash 部分,记得之前将 URL 使用微信分享时会丢失 hash 部分。
前端开发单页应用,为什么在 url #后传参
问号以及后面的结构浏览器通常称为 Search,服务端通常称为 Query,这部分是会传到服务器的。而井号以及后面的部分浏览器端是称为 Hash,是不会传到服务器上的。
通常单页面应用的路由及页面间的传参不需要服务器处理,也就不需要传给服务器。
最重要的一点是如果在 Search中传参整个页面是会刷新的,而单页面应用的设计就是想要避免用户在使用过程中页面刷新。Hash 的修改通常就不会刷新。
例如从列表页进入详情页,直接 js 获取详情页内容然后直接在当前页面显示了详情页,这时候如果变更 url 前半部分会照成浏览器重新加载页面。
当然现在新浏览器支持不重新加载页面变更 url,但是还是老问题,为了兼容老浏览器很多还是只变更 # 后面。
? 传参走的是 form 提交,浏览器认为 url 变了会刷新页面的,是同步的做法,现在都是异步,查询都是走 XHR 或者 fetch 的,不需要刷新页面,#传参是个大框架都支持的路由传参方法,不过也有缺点,有些第三方 API 默认会过滤#传的参数,导致 redirect 失败,比如微信的 API,号称是为了安全性
用#hash 还有个好处上面都没提到,就是 http 的 referer(引用) 会带上?search,不会带上#hash。如果页面资源多、?search 也很长的话,就会产生许多带有很长?search 的 referer,浪费带宽;而且带有?search 的 referer 请求外部资源,还有可能把敏感信息暴露给第三方。
js 有什么原生的方法可以吧 object 转为 string key=value 形式吗?
例如对象 { test:1, test2:2 } 转成字符串 test=1&test2=2
Object
.entries(o)
.reduce((arr, [k, v])
=> arr.concat(encodeURIComponent(k) + '=' + encodeURIComponent(v)), [])
.join('&')
//在 Node.js 里自带 querystring 模块
const querystring = require('querystring')
querystring.stringify(obj)
渲染模式
以前后端渲染模式,访问一个页面---浏览器发出请求,服务器后台读取数据,渲染模板,浏览器拿到 HTML 开始渲染,请求图片等资源,用户看到一个完整网页;
现在浏览器渲染模式,访问一个页面---浏览器发出请求,从 CDN 或服务器得到静态页面(此页面只包含极少部分页面内容),浏览器开始渲染,看到部分静态内容,请求静态资源,解析 js 脚本,发出请求,服务器响应请求,返回数据,js 拿到数据,拼装内容,浏览器渲染,用户看到完整网页