browserHistory和hashHistory
首先 browserHistory 其實使用的是 HTML5 的 History API,瀏覽器提供相應的接口來修改瀏覽器的歷史記錄树枫,不少方法還是實驗性的,而且 E10 以下不支持;而 hashHistory 是通過改變地址后面的 hash 來改變?yōu)g覽器的歷史記錄;
History API 提供了 pushState() 和 replaceState() 方法來增加或替換歷史記錄茂浮。而 hash 沒有相應的方法,所以并沒有替換歷史記錄的功能。但 react-router 通過 polyfill 實現(xiàn)了此功能席揽,具體實現(xiàn)沒有看顽馋,好像是使用 sessionStorage。
另一個原因是 hash 部分并不會被瀏覽器發(fā)送到服務端幌羞,也就是說不管是請求 #foo 還是 #bar 寸谜,服務只知道請求了 index.html 并不知道 hash 部分的細節(jié)。而 History API 需要服務端支持属桦,這樣服務端能獲取請求細節(jié)熊痴。
還有一個原因是因為有些應該會忽略 URL 中的 hash 部分,記得之前將 URL 使用微信分享時會丟失 hash 部分聂宾。
前端開發(fā)單頁應用果善,為什么在 url #后傳參
問號以及后面的結構瀏覽器通常稱為 Search,服務端通常稱為 Query系谐,這部分是會傳到服務器的巾陕。而井號以及后面的部分瀏覽器端是稱為 Hash,是不會傳到服務器上的纪他。
通常單頁面應用的路由及頁面間的傳參不需要服務器處理鄙煤,也就不需要傳給服務器。
最重要的一點是如果在 Search中傳參整個頁面是會刷新的止喷,而單頁面應用的設計就是想要避免用戶在使用過程中頁面刷新馆类。Hash 的修改通常就不會刷新。
例如從列表頁進入詳情頁弹谁,直接 js 獲取詳情頁內容然后直接在當前頁面顯示了詳情頁乾巧,這時候如果變更 url 前半部分會照成瀏覽器重新加載頁面。
當然現(xiàn)在新瀏覽器支持不重新加載頁面變更 url预愤,但是還是老問題沟于,為了兼容老瀏覽器很多還是只變更 # 后面。
? 傳參走的是 form 提交植康,瀏覽器認為 url 變了會刷新頁面的旷太,是同步的做法,現(xiàn)在都是異步销睁,查詢都是走 XHR 或者 fetch 的供璧,不需要刷新頁面,#傳參是個大框架都支持的路由傳參方法冻记,不過也有缺點睡毒,有些第三方 API 默認會過濾#傳的參數(shù),導致 redirect 失敗冗栗,比如微信的 API演顾,號稱是為了安全性
用#hash 還有個好處上面都沒提到供搀,就是 http 的 referer(引用) 會帶上?search,不會帶上#hash钠至。如果頁面資源多葛虐、?search 也很長的話,就會產生許多帶有很長?search 的 referer棉钧,浪費帶寬屿脐;而且?guī)в?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)
渲染模式
以前后端渲染模式,訪問一個頁面---瀏覽器發(fā)出請求愧捕,服務器后臺讀取數(shù)據(jù)奢驯,渲染模板,瀏覽器拿到 HTML 開始渲染次绘,請求圖片等資源瘪阁,用戶看到一個完整網頁;
現(xiàn)在瀏覽器渲染模式邮偎,訪問一個頁面---瀏覽器發(fā)出請求管跺,從 CDN 或服務器得到靜態(tài)頁面(此頁面只包含極少部分頁面內容),瀏覽器開始渲染禾进,看到部分靜態(tài)內容豁跑,請求靜態(tài)資源,解析 js 腳本泻云,發(fā)出請求艇拍,服務器響應請求,返回數(shù)據(jù)宠纯,js 拿到數(shù)據(jù)卸夕,拼裝內容,瀏覽器渲染婆瓜,用戶看到完整網頁