1.router實現(xiàn)原理
一句話:實現(xiàn)URL與UI界面的同步。其中在react-router中,URL對應(yīng)Location對象,而UI是由react?components來決定的,這樣就轉(zhuǎn)變成location與components之間的同步問題。
老瀏覽器的history: 主要通過hash來實現(xiàn),對應(yīng)createHashHistory
高版本瀏覽器: 通過html5里面的history,對應(yīng)createBrowserHistory
node環(huán)境下: 主要存儲在memeory里面,對應(yīng)createMemoryHistory
2.hash路由和broswer路由的區(qū)別
3.瀏覽器緩存機制
? ?從緩存位置上來說分為四種,并且各自有優(yōu)先級,當依次查 找 緩存且都沒有命中的時候,才會去請求網(wǎng)絡(luò)。
? ?Service Worker
? ? Memory Cache
? ? Disk Cache
? ?Push Cache
1.Service Worker
Service Worker 是運行在瀏覽器背后的獨立線程,一般可以用來實現(xiàn)緩存功能。使用 Service Worker的話,傳輸協(xié)議必須為 HTTPS。因為 Service Worker 中涉及到請求攔截,所以必須使用 HTTPS 協(xié)議來保障安全。Service Worker 的緩存與瀏覽器其他內(nèi)建的緩存機制不同,它可以讓我們自由控制緩存哪些文件、如何匹配緩存、如何讀取緩存,并且緩存是持續(xù)性的。
Service Worker 實現(xiàn)緩存功能一般分為三個步驟:首先需要先注冊 Service Worker,然后監(jiān)聽到 install 事件以后就可以緩存需要的文件,那么在下次用戶訪問的時候就可以通過攔截請求的方式查詢是否存在緩存,存在緩存的話就可以直接讀取緩存文件,否則就去請求數(shù)據(jù)。
當 Service Worker 沒有命中緩存的時候,我們需要去調(diào)用 fetch 函數(shù)獲取數(shù)據(jù)。也就是說,如果我們沒有在 Service Worker 命中緩存的話,會根據(jù)緩存查找優(yōu)先級去查找數(shù)據(jù)。但是不管我們是從 Memory Cache 中還是從網(wǎng)絡(luò)請求中獲取的數(shù)據(jù),瀏覽器都會顯示我們是從 Service Worker 中獲取的內(nèi)容。
2.Memory Cache
Memory Cache 也就是內(nèi)存中的緩存,主要包含的是當前中頁面中已經(jīng)抓取到的資源,例如頁面上已經(jīng)下載的樣式、腳本、圖片等。讀取內(nèi)存中的數(shù)據(jù)肯定比磁盤快,內(nèi)存緩存雖然讀取高效,可是緩存持續(xù)性很短,會隨著進程的釋放而釋放。一旦我們關(guān)閉 Tab 頁面,內(nèi)存中的緩存也就被釋放了。
那么既然內(nèi)存緩存這么高效,我們是不是能讓數(shù)據(jù)都存放在內(nèi)存中呢?
這是不可能的。計算機中的內(nèi)存一定比硬盤容量小得多,操作系統(tǒng)需要精打細算內(nèi)存的使用,所以能讓我們使用的內(nèi)存必然不多。
當我們訪問過頁面以后,再次刷新頁面,可以發(fā)現(xiàn)很多數(shù)據(jù)都來自于內(nèi)存緩存
內(nèi)存緩存中有一塊重要的緩存資源是preloader相關(guān)指令(例如<link rel="prefetch">)下載的資源。總所周知preloader的相關(guān)指令已經(jīng)是頁面優(yōu)化的常見手段之一,它可以一邊解析js/css文件,一邊網(wǎng)絡(luò)請求下一個資源。
3.Disk Cache
Disk Cache 也就是存儲在硬盤中的緩存,讀取速度慢點,但是什么都能存儲到磁盤中,比之 Memory Cache 勝在容量和存儲時效性上。
在所有瀏覽器緩存中,Disk Cache 覆蓋面基本是最大的。它會根據(jù) HTTP Herder 中的字段判斷哪些資源需要緩存,哪些資源可以不請求直接使用,哪些資源已經(jīng)過期需要重新請求。并且即使在跨站點的情況下,相同地址的資源一旦被硬盤緩存下來,就不會再次去請求數(shù)據(jù)。絕大部分的緩存都來自 Disk Cache,關(guān)于 HTTP 的協(xié)議頭中的緩存字段,我們會在下文進行詳細介紹。
瀏覽器會把哪些文件丟進內(nèi)存中?哪些丟進硬盤中?
關(guān)于這點,網(wǎng)上說法不一,不過以下觀點比較靠得?。?/p>
對于大文件來說,大概率是不存儲在內(nèi)存中的,反之優(yōu)先
當前系統(tǒng)內(nèi)存使用率高的話,文件優(yōu)先存儲進硬盤
4.Push Cache
Push Cache(推送緩存)是 HTTP/2 中的內(nèi)容,當以上三種緩存都沒有命中時,它才會被使用。它只在會話(Session)中存在,一旦會話結(jié)束就被釋放,并且緩存時間也很短暫,在Chrome瀏覽器中只有5分鐘左右,同時它也并非嚴格執(zhí)行HTTP頭中的緩存指令。
Push Cache 在國內(nèi)能夠查到的資料很少,也是因為 HTTP/2 在國內(nèi)不夠普及。這里推薦閱讀Jake Archibald的HTTP/2 push is tougher than I thought這篇文章,文章中的幾個結(jié)論:
所有的資源都能被推送,并且能夠被緩存,但是 Edge 和 Safari 瀏覽器支持相對比較差
可以推送 no-cache 和 no-store 的資源
一旦連接被關(guān)閉,Push Cache 就被釋放
多個頁面可以使用同一個HTTP/2的連接,也就可以使用同一個Push Cache。這主要還是依賴瀏覽器的實現(xiàn)而定,出于對性能的考慮,有的瀏覽器會對相同域名但不同的tab標簽使用同一個HTTP連接。
Push Cache 中的緩存只能被使用一次
瀏覽器可以拒絕接受已經(jīng)存在的資源推送
你可以給其他域名推送資源
如果以上四種緩存都沒有命中的話,那么只能發(fā)起請求來獲取資源了。
那么為了性能上的考慮,大部分的接口都應(yīng)該選擇好緩存策略,通常瀏覽器緩存策略分為兩種:強緩存和協(xié)商緩存,并且緩存策略都是通過設(shè)置 HTTP Header 來實現(xiàn)的。

強緩存:不會向服務(wù)器發(fā)送請求,直接從緩存中讀取資源,在chrome控制臺的Network選項中可以看到該請求返回200的狀態(tài)碼,并且Size顯示from disk cache或from memory cache。強緩存可以通過設(shè)置兩種 HTTP Header 實現(xiàn):Expires 和 Cache-Control。
1.Expires
緩存過期時間,用來指定資源到期的時間,是服務(wù)器端的具體的時間點。也就是說,Expires=max-age + 請求時間,需要和Last-modified結(jié)合使用。Expires是Web服務(wù)器響應(yīng)消息頭字段,在響應(yīng)http請求時告訴瀏覽器在過期時間前瀏覽器可以直接從瀏覽器緩存取數(shù)據(jù),而無需再次請求。
Expires 是 HTTP/1 的產(chǎn)物,受限于本地時間,如果修改了本地時間,可能會造成緩存失效。Expires: Wed, 22 Oct 2018 08:41:00 GMT表示資源會在 Wed, 22 Oct 2018 08:41:00 GMT 后過期,需要再次請求。
2.Cache-Control
在HTTP/1.1中,Cache-Control是最重要的規(guī)則,主要用于控制網(wǎng)頁緩存。比如當Cache-Control:max-age=300時,則代表在這個請求正確返回時間(瀏覽器也會記錄下來)的5分鐘內(nèi)再次加載資源,就會命中強緩存。
3.Expires和Cache-Control兩者對比
其實這兩者差別不大,區(qū)別就在于 Expires 是http1.0的產(chǎn)物,Cache-Control是http1.1的產(chǎn)物,兩者同時存在的話,Cache-Control優(yōu)先級高于Expires;在某些不支持HTTP1.1的環(huán)境下,Expires就會發(fā)揮用處。所以Expires其實是過時的產(chǎn)物,現(xiàn)階段它的存在只是一種兼容性的寫法。
強緩存判斷是否緩存的依據(jù)來自于是否超出某個時間或者某個時間段,而不關(guān)心服務(wù)器端文件是否已經(jīng)更新,這可能會導致加載文件不是服務(wù)器端最新的內(nèi)容,那我們?nèi)绾潍@知服務(wù)器端內(nèi)容是否已經(jīng)發(fā)生了更新呢?此時我們需要用到協(xié)商緩存策略。
五、協(xié)商緩存
協(xié)商緩存就是強制緩存失效后,瀏覽器攜帶緩存標識向服務(wù)器發(fā)起請求,由服務(wù)器根據(jù)緩存標識決定是否使用緩存的過程,主要有以下兩種情況:
協(xié)商緩存生效,返回304和Not Modified
協(xié)商緩存失效,返回200和請求結(jié)果
協(xié)商緩存可以通過設(shè)置兩種 HTTP Header 實現(xiàn):Last-Modified 和 ETag 。
緩存機制
強制緩存優(yōu)先于協(xié)商緩存進行,若強制緩存(Expires和Cache-Control)生效則直接使用緩存,若不生效則進行協(xié)商緩存(Last-Modified / If-Modified-Since和Etag / If-None-Match),協(xié)商緩存由服務(wù)器決定是否使用緩存,若協(xié)商緩存失效,那么代表該請求的緩存失效,返回200,重新返回資源和緩存標識,再存入瀏覽器緩存中;生效則返回304,

八、用戶行為對瀏覽器緩存的影響
所謂用戶行為對瀏覽器緩存的影響,指的就是用戶在瀏覽器如何操作時,會觸發(fā)怎樣的緩存策略。主要有 3 種:
打開網(wǎng)頁,地址欄輸入地址: 查找 disk cache 中是否有匹配。如有則使用;如沒有則發(fā)送網(wǎng)絡(luò)請求。
普通刷新 (F5):因為 TAB 并沒有關(guān)閉,因此 memory cache 是可用的,會被優(yōu)先使用(如果匹配的話)。其次才是 disk cache。
強制刷新 (Ctrl + F5):瀏覽器不使用緩存,因此發(fā)送的請求頭部均帶有Cache-control: no-cache(為了兼容,還帶了Pragma: no-cache),服務(wù)器直接返回 200 和最新內(nèi)容。
原地址:http://www.itdecent.cn/p/54cc04190252
4.函數(shù)回流/重繪
當瀏覽器重新渲染文檔中的元素時需要?重新計算它們的位置和幾何形狀,我們稱之為回流?;亓鲿枞脩粼跒g覽器中的操作,因此理解提升回流時間是非常有幫助的。
你應(yīng)該批量地觸發(fā)回流或重繪,但是要節(jié)制地使用這些方法。盡量不處理DOM也很重要??梢允褂?a target="_blank">DocumentFragment,一個輕量級的文檔對象。你可以把它作為一種方法來提取文檔樹的一部分,或創(chuàng)建一個新的文檔“片段”。與其不斷地添加DOM節(jié)點,不如使用文檔片段后只執(zhí)行一次DOM插入操作,以避免過多的回流。
例如,我們寫一個函數(shù)給一個元素添加20個div。如果只是簡單地每次append一個div到元素中,這會觸發(fā)20次回流。
function addDivs(element) {
? var div;
? for (var i = 0; i < 20; i ++) {
? ? div = document.createElement('div');
? ? div.innerHTML = 'Heya!';
? ? element.appendChild(div);
? }
}
源地址:http://www.cnblogs.com/Lee-ahao/p/9704482.html
5.冒泡排序
6.js異步加載
1.defer:defer
2.async:async(asynchronous)
3.動態(tài)添加script
.functionasyncLoaded(url,callBack){/*url為js的鏈接,callBack為url的js中的函數(shù)(該函數(shù)調(diào)用應(yīng)該寫到匿名函數(shù)中,如function(){console.log(div.getScrollOffset())})*/varscript = document.createElement('script');
? ? script.type = 'text/javascript';
? ? /*if else 這幾句話必須要寫到這位置處,不能放最后,因為if中js加載中script.readyState存在好幾種狀態(tài),
? ? 只有狀態(tài)改變‘readystatechange’事件才會觸發(fā),但現(xiàn)在瀏覽器加載速度很快,當解析到該事件時JS有可能已經(jīng)加載完,
? ? 所以事件根本不會觸發(fā),所以要寫到前面*/if(script.readystate){//兼容IEscript.onreadystatechange =function() {//狀態(tài)改變事件才觸發(fā)if(script.readyState == 'loaded' || script.readyState == 'complete'){? ?
? ? ? ? ? ? ? ? callBack();
? ? ? ? ? ? ? ? script.onreadystatechange =null;? ? ? ?
? ? ? ? ? ? }
? ? ? ? }
? ? }else{
? ? ? ? script.onload =function(e){
? ? ? ? ? ? callBack();
? ? ? ? }
? ? }? ? ? ?
? ? script.src = url;
? ? document.body.appendChild(script);
}