@
目錄
HTML
1. 如何了解HTML語義化
2. 預設情況下,哪些HTML标簽是塊級元素、哪些是内聯元素
3. HTML5 新增内容和 API
CSS
1. 盒子模型
2. margin 縱向重疊
3. margin 負值
4. BFC(塊級格式化上下文)
5. float布局
6. flex布局
7. 三欄布局
8. CSS定位
9. 居中對齊實作方式
10. line-height的繼承問題
11. CSS長度機關
12. CSS響應式媒體查詢
13. 網頁視口尺寸
14. CSS3 vw / vh
JS
1. ES6
2. 資料類型與檢測
3. 深拷貝和淺拷貝
4. 原型與原型鍊(三座大山之一)
prototype(顯式原型)
_proto _ (隐式原型)
constructor ( 指向建立該對象的構造函數)
原型鍊
原型與原型鍊的終極圖
instanceof 原理
繼承方式
5. 作用域、this 和閉包 (三座大山之二)
作用域
作用域鍊
this
閉包
6. 異步 (三座大山之三)
單線程與多線程
同步與異步
事件循環(Event Loop)
Promise
async與await
異步加載JS方式
7. DOM 與 BOM
DOM
BOM
8. 事件流
事件捕獲
事件冒泡(預設)
DOM 标準事件流
阻止事件冒泡/捕獲
阻止預設事件
事件代理/委托
9. 跨域
同源政策
不存在跨域的情況(無視同源政策)
常見的幾種跨域方法
安全
10. HTTP
HTTP三大特點
HTTP 消息結構
HTTP 狀态碼
HTTP 請求方法
HTTP 緩存
11. 手寫常見JS方法
工具
1. Git
2. 浏覽器
浏覽器從輸入URL到渲染完頁面的整個過程
浏覽器渲染過程
3. 其他
yarn
gulp
babel
vConsole
Vue
1. MVVM
2. 生命周期
Vue2生命周期
Vue3生命周期
3. computed 與 watch
computed(計算屬性)
watch(監聽屬性)
4. v-if 與 v-show
v-if
v-show
5. data 必須是一個函數,而不是對象
6. diff 算法
7. for 循環中 key 的作用
8. 雙向綁定v-model
9. 元件的通信
父元件向子元件傳值(props)
子元件向父元件傳值($emit)
兄弟元件傳值(EventBus)
Vuex
10. 路由
router-link
router.push
$router 和 $route 的差別
router.js (含路由懶加載和路由鑒權)
11. 其他
vue3中CompositionAPI
Vue中對axios的封裝(含攔截器)
HTML5語義化
讓人更容易讀懂(代碼結構清晰,增加代碼的可讀性)
讓搜尋引擎更容易讀懂(SEO),搜尋引擎爬蟲會根據不同的标簽來賦予不同的權重
語義化标簽 : <code>header</code> <code>nav</code> <code>main</code> <code>article</code> <code>section</code> <code>aside</code> <code>footer</code>
塊級元素:<code>display: block/table</code>,有<code>div</code> <code>div</code> <code>h1</code> <code>h2</code> <code>table</code> <code>ul</code> <code>ol</code> <code>li</code> <code>p</code>等
内聯元素:<code>display: inline/inline-block</code>,有<code>span</code> <code>img</code> <code>input</code> <code>button</code> <code>i</code> <code>b</code>等
HTML5 新增内容和 API
classList 屬性
querySelector() 與 querySelectorAll()
getElementsByClassName()
自定義資料屬性
本地存儲
insertAdjacentHtml()、insertAdjacentText()、insertAdjacentElement()
内容可編輯
預加載
CSS盒子模型
box-sizing屬性
CSS盒子模型包含2種:
W3C标準盒子模型(<code>box-sizing: content-box</code> ,預設),寬高不受 padding、border影響
IE怪異盒子模型 (<code>box-sizing: border-box</code>),寬高受 padding、border影響
相鄰元素的<code>margin-top</code>和<code>margin-bottom</code>會重疊
空内容的元素也會重疊
思考:如下代碼,<code>AAA</code>和<code>BBB</code>之間的間距是多少 ?
答案是 15px

<code>margin-top</code> 負值,元素會上移
<code>margin-left</code> 負值,元素會左移
<code>margin-right</code> 負值,右側元素會左移,自身不受影響
<code>margin-bottom</code> 負值,下方元素會上移,自身不受影響
3分鐘了解BFC
具有 BFC 特性的元素可以看作是隔離了的獨立容器,容器裡面的元素不會在布局上影響到外面的元素
隻要元素滿足下面任一條件即可觸發 BFC 特性:
根元素(即<code><html></code>标簽)
浮動元素 float 不為 none (為 <code>left</code>、<code>right</code>)
絕對定位元素 position 不為 static 或 relative。(為 <code>absolute</code> 、 <code>fixed</code>)
overflow 的值不為 visible 的塊元素(為 <code>auto</code>、<code>scroll</code>、<code>hidden</code>)
display 的值為<code>inline-block</code>、<code>flex</code>、<code>grid</code>、<code>table</code>、<code>table-cell</code>、<code>table-caption</code>...
同一BFC内:
Box會在垂直方向上一個接一個的放置
垂直方向的距離由margin決定(屬于同一個BFC的兩個相鄰Box的margin會發生重疊,與方向無關)
每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動也是如此
BFC的區域不會與float的元素區域重疊
計算BFC的高度時,浮動子元素也參與計算
BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面元素,反之亦然
應用:
分屬于不同的BFC時,可以防止margin重疊
清除内部浮動
自适應多欄布局
flex布局
flex平分布局
實作三欄布局的8種方式:
浮動布局
定位布局
表格布局
網格布局
calc函數布局
聖杯布局
雙飛翼布局
面試常考的聖杯布局和雙飛翼布局:
三欄布局,中間一欄最先加載和渲染(内容最重要)
兩側内容固定,中間内容随着寬度自适應
一般用于PC端
css中position屬性詳解
思考:<code>relative</code>、<code>absolute</code>、<code>fixed</code>依據什麼定位?
答案:
<code>relative</code>:依據自身定位(相對的是它原本在文檔流中的位置而進行的偏移)。在最外層時,是以<code><body></code>标簽為定位原點的。
<code>absolute</code>:依據最近一層的定位元素定位(根據<code>postion</code>非<code>static</code>的祖先類元素進行定位)。在無父級是<code>postion</code>非<code>static</code>定位時,是以<code><html></code>作為原點定位。
<code>fixed</code>:根據視窗為原點進行偏移定位 (也就是說它不會根據滾動條的滾動而進行偏移)
css居中常見方法總結
思考: 以下代碼中<code>p</code>标簽的行高是多少?
答案是 40px
寫具體數值,如<code>body{ line-height: 30px;}</code>,則繼承該值 ( <code>p</code> 的行高就是<code>30px</code> )
寫比例,如<code>body{ line-height: 2;}</code> ,則繼承該比例 ( <code>p</code> 的行高就是<code>16px*2 = 32px</code> ) p字型大小的2倍
寫百分比(有坑),如<code>body{ line-height: 200%;}</code> ,則繼承計算出來的值 ( <code>p</code> 的行高就是<code>20px*2 = 40px</code> ) body字型大小的2倍
<code>px</code> 固定的像素,一旦設定了就無法因為适應頁面大小而改變。
<code>em</code> 相對于父元素的長度機關。(不常用)
<code>rem</code> 相對于根<code><html></code>元素的長度機關。(常用)
<code>rpx</code> 微信小程式的相對長度機關。小程式規定螢幕寬為750rpx。如在 iPhone6 上,螢幕寬度為375px,共有750個實體像素,則750rpx = 375px = 750實體像素,1rpx = 0.5px = 1實體像素。(僅微信小程式)
假如一個終端的分辨率小于 980px,那麼可以這樣寫:
假如我們要設定相容 iPad 和 iPhone 的視圖,那麼可以這樣設定:
媒體查詢一般配合<code>rem</code>機關實作響應式,是以<code>rem</code>具有<code>階梯性</code>的弊端
螢幕高度 window.screen.height (顯示器螢幕裝置高度)
網頁視口高度 window.innerHeight (去掉浏覽器自身的頭部和底部後的高度,含滾動條高)
body高度 document.body.clientHeight (頁面内容的真實高度)
神圖
寬度同理 略~
<code>vw</code> 網頁視口寬度的1% ( <code>window.innerWidth = 1vw</code> )
<code>vh</code> 網頁視口高度的1% ( <code>window.innerHeight = 1vh</code> )
<code>vmin</code> 選取<code>vw</code>和<code>vh</code>中最小的那個
<code>vmax</code> 選取<code>vw</code>和<code>vh</code>中最大的那個
檢視ES6專輯
ES6之 let 和 const 關鍵字
ES6之 解構指派
ES6之 擴充運算符
ES6之 字元串新特性
ES6之 數值新特性
ES6之 數組新特性
ES6之 函數優化(預設參數、剩餘參數、 箭頭函數)
ES6之 Promise
ES6之 async/await
ES6之 class(類)
ES6之 Map和Set
ES6之 import和export
ES6之 Generator 函數
ES6之 for...of 循環
js檢測資料類型的幾種方法總結
JavaScript 資料類型:
Number (基本類型)
String (基本類型)
Boolean (基本類型)
null (基本類型)
undefined (基本類型)
symbol (ES6 - 基本類型)
bigInt (ES10 - 基本類型)
object (引用類型,包含 function、[ ]、{ })
基本類型的特點:直接存儲在棧(stack)記憶體中的資料
引用類型的特點:存儲的是該對象在棧中引用,真實的資料存放在堆(heap)記憶體中
JavaScript中的深拷貝和淺拷貝
深拷貝和淺拷貝最根本的差別在于是否是真正擷取了一個對象的拷貝實體,而不是引用。
淺拷貝隻拷貝一層對象的屬性,而深拷貝則遞歸拷貝了所有層級。
深拷貝在計算機中開辟了一塊新的記憶體位址用于存放拷貝的對象
淺拷貝僅僅是指向被拷貝的記憶體位址,如果原位址中對象被改變了,那麼淺拷貝出來的對象也會相應改變
深入了解javascript之原型和原型鍊
所有函數(僅限函數)擁有 <code>prototype</code> 屬性
<code>prototype</code> 對象用于放某同一類型執行個體的共享屬性和方法,實質上是為了記憶體着想。
所有對象擁有 <code>_proto _</code> 屬性
<code>_proto _</code> 指向誰?分以下三種情況:
每個原型對象都可以通過對象<code>.constructor</code> 指向建立該對象的構造函數
下圖中由互相關聯的原型組成的鍊狀結構就是原型鍊,也就是藍色的這條線。
這個圖要是看懂了,原型與原型鍊就基本摸清了。
<code>instanceof</code> 隻能用來判斷對象類型,原始類型不可以。并且所有對象類型<code>instanceof Object</code> 都是 <code>true</code>
<code>instanceof</code> 的内部機制是通過判斷對象的原型鍊中是不是能找到類型的 <code>prototype</code>。
Instanceof的判斷隊則是:沿着s1的__proto__這條線來找,同時沿着Student的prototype這條線來找,如果兩條線能找到同一個引用,即同一個對象,那麼就傳回true。如果找到終點還未重合,則傳回false。這就很好地解釋了上述代碼的輸出結果啦。
JavaScript中的繼承方式
在 Javascript 中,作用域分為 全局作用域 和 函數作用域
全局作用域
代碼在程式的任何地方都能被通路,<code>window 對象</code>的内置屬性都擁有全局作用域。
函數作用域
在固定的代碼片段才能被通路
作用域有上下級關系,上下級關系的确定就看函數是在哪個作用域下建立的。如上,fn作用域下建立了bar函數,那麼“fn作用域”就是“bar作用域”的上級。
作用域最大的用處就是隔離變量,不同作用域下同名變量不會有沖突。
ES6之塊級作用域
ES6之let關鍵字
變量取值:到建立這個變量的函數的作用域中向上取值,而不是調用這個函數時向上取值,
如果在目前作用域中沒有查到值,就會向上級作用域去查,直到查到全局作用域,這麼一個查找過程形成的鍊條就叫做作用域鍊。
思考:以下代碼輸出什麼?
從建立的函數向上取值,而不是調用函數時向上取值
徹底了解JavaScript中this指向
this永遠指向的是最後調用它的對象,也就是看它執行的時候是誰調用的
特别注意:
匿名函數的自我執行,沒有被上級對象調用,是以this指向window
<code>setTimeout(function () { console.log(this) });</code> ,this指向window
<code>setTimeout(() => { console.log(this) });</code> ,this指向上下文
構造函數中的this,指向執行個體對象
<code>bind</code>、<code>call</code>、<code>apply</code> 可以改變 this 指向
JavaScript中call,apply,bind方法的總結
JavaScript閉包
閉包就是指有權通路另一個函數作用域中的變量的函數。
建立閉包的最常見的方式就是在一個函數内建立另一個函數,通過另一個函數通路這個函數的局部變量
閉包的特性:
函數嵌套函數
函數内部可以引用外部的參數和變量
參數和變量不會被垃圾回收機制回收
JavaScript是單線程語言(可以說這是JavaScript最核心也是最基本的特性)
浏覽器的核心是多線程的
雖然JavaScript是單線程的,可是浏覽器内部不是單線程的。
一些I/O操作、定時器的計時和事件監聽(click, keydown...)等都是由浏覽器提供的其他線程來完成的。
同步:是指在主線程上排隊執行的任務,隻有前一個任務執行完畢,才能繼續執行下一個任務。
當我們打開網站時,網站的渲染過程,比如元素的渲染,其實就是一個同步任務
異步:是指不進入主線程,而進入任務隊列的任務,隻有任務隊列通知主線程,某個異步任務可以執行了,該任務才會進入主線程。
當我們打開網站時,像圖檔加載等網絡請求(ajax、axios)、定時任務(setTimeout),其實就是一個異步任務
淺談事件循環Event Loop
事件循環機制:
首先判斷JS是同步還是異步,同步就進入主線程,異步就進入<code>event table</code>
異步任務在<code>event table</code>中注冊函數,當滿足觸發條件後,被推入消息隊列(<code>event queue</code>)
同步任務進入主線程後一直執行,直到主線程空閑時,才會去消息隊列中檢視是否有可執行的異步任務,如果有就推入主線程中
異步任務又可以分為:
<code>macrotask(宏任務)</code>:
等待執行棧和微任務隊列都執行完畢才會執行,并且在執行完每一個宏任務之後,會去看看微任務隊列有沒有新添加的任務,如果有,會先将微任務隊列中的任務清空,才會繼續執行下一個宏任務
包括:script代碼塊,setTimeout,setInterval,I/O
<code>microtask(微任務)</code>:
當執行棧中的代碼執行完畢,會在執行宏任務隊列之前先看看微任務隊列中有沒有任務,如果有會先将微任務隊列中的任務清空才會去執行宏任務隊列
包括:Promise,nextTick,callback,Object.observe,MutationObserver
執行的順序是 <code>執行棧中的代碼 => 微任務 => 宏任務 => 微任務 => 宏任務 => ...</code>。
DOM事件也是基于Event Loop,但不是異步
異步任務的執行也是有先後順序的:
執行一個宏任務,過程中如果遇到微任務,就将其放到微任務的【事件隊列】裡
目前宏任務執行完成後,會檢視微任務的【事件隊列】,并将裡面全部的微任務依次執行完
徹底掌握 Promise
手寫一個Promise
<code>Promise</code> 是異步程式設計的一種解決方案,有三種狀态:
<code>pending</code> (等待态)
<code>fulfiled</code> (成功态)
<code>rejected</code> (失敗态)
一旦 <code>Promise</code> 被 <code>resolve</code> 或 <code>reject</code>,不能再遷移至其他任何狀态(即狀态 <code>immutable</code>)。創造 <code>promise</code> 執行個體後,它會立即執行。
基本過程:
初始化 <code>Promise</code> 狀态(<code>pending</code>);
立即執行 <code>Promise</code> 中傳入的 <code>fn</code> 函數,将<code>Promise</code> 内部 <code>resolve</code>、<code>reject</code> 函數作為參數傳遞給 <code>fn</code> ,按事件機制時機處理;
執行 <code>then(…)</code> 注冊回調處理數組(<code>then</code> 方法可被同一個 <code>promise</code> 調用多次);
<code>Promise</code> 裡的關鍵是要保證,<code>then</code>方法傳入的參數 <code>onFulfilled</code> 和 <code>onRejected</code>,必須在<code>then</code>方法被調用的那一輪事件循環之後的新執行棧中執行;
簡單用法:
細說 async/await
核心:
執行 async 函數,預設傳回一個 promise 對象
await 相當于 promise 的 then
try...catch 可捕獲異常,代替了 promise 的 catch
思考:以下代碼輸出順序
答案
await 下面所有的代碼都是異步
1. 匿名函數自調動态建立script标簽加載js
2. async屬性
3. defer屬性
DOM對象和BOM對象
DOM (Document Object Model)是 W3C 的标準,是指文檔對象模型(樹結構)。
DOM 定義了通路和操作 HTML 文檔的标準方法。通過它,可以通路HTML文檔的所有元素。
1. HTML DOM 樹:
2. DOM 節點:
根據 W3C 的 HTML DOM 标準,HTML 文檔中的所有内容都是節點(NODE):
文檔節點:整個文檔(document對象)
元素節點:每個 HTML 元素(element 對象)
文本節點:HTML 元素内的文本(text對象)
屬性節點:每個 HTML 屬性(attribute對象)
注釋節點:注釋(comment對象)
3. DOM 查找:
4. DOM 操作:
5. DOM 優化:
DOM 操作都是代價昂貴的操作,它會導緻 WEB 應用程式的 UI 反應遲鈍。是以,應當盡可能減少這類過程的發生。
将頻繁的 DOM 操作改成一次性操作:
BOM(Browser Object Model)是指浏覽器對象模型,可以對浏覽器視窗進行通路和操作。
使用 BOM,開發者可以移動視窗、改變狀态欄中的文本以及執行其他與頁面内容不直接相關的動作。使 JavaScript 有能力與浏覽器"對話"。
Window 對象 (<code>window.alert()</code>、<code>window.open()</code>、<code>window.setTimeout()</code> ...)
Navigator 對象(<code>navigator.userAgent</code> ...)
Screen 對象 (<code>screen.width</code>、<code>screen.height</code> ...)
Location 對象 (<code>location.href</code>、<code>location.reload()</code>、<code>location.replace()</code> ...)
History 對象(<code>history.forward()</code>、<code>history.back()</code> ...)
JavaScript 事件流
事件傳播的順序對應浏覽器的兩種事件流模型:
冒泡型事件流中click事件傳播順序為 <code><div> => <body> => <html> => document</code> (預設)
捕獲型事件流中click事件傳播順序為 <code>document => <html> => <body> => <div></code>
綁定事件時通過addEventListener函數,它有三個參數,第三個參數若是true,則表示采用事件捕獲,若是false(預設),則表示采用事件冒泡。
<code>element.addEventListener(event, function, useCapture)</code>
第三個參數<code>useCapture</code>,可選。布爾值,指定事件是否在捕獲或冒泡階段執行:
<code>true</code> - 事件句柄在捕獲階段執行
<code>false</code>(預設)- 事件句柄在冒泡階段執行
使用 <code>event.stopPropagation()</code> 起到阻止捕獲和冒泡階段中目前事件的進一步傳播。
W3C的方法是: <code>event.stopPropagation()</code>
IE則是使用: <code>event.cancelBubble = true</code>
相容IE的寫法:
W3C的方法是: <code>event.preventDefault()</code>
IE則是使用: <code>event.returnValue = false</code>
既然是說預設行為,當然是元素必須有預設行為才能被取消,如果元素本身就沒有預設行為,調用當然就無效了。
事件代理的原理用到的就是事件冒泡和目标元素,把事件處理器添加到父元素,等待子元素事件冒泡,并且父元素能夠通過target(IE為srcElement)判斷是哪個子元素,進而做相應處理。
JS 跨域詳解
跨域是指從一個域名的網頁去請求另一個域名的資源。比如從 <code>www.baidu.com</code> 頁面去請求 <code>www.google.com</code> 的資源。
非同源,在請求資料時,浏覽器會在控制台中報一個異常,提示拒絕通路。它是由浏覽器的同源政策造成的,是浏覽器對JavaScript施加的安全限制。
同源政策是浏覽器最核心也最基本的安全功能。如果缺少了同源政策,則浏覽器的正常功能可能都會受到影響。可以說Web是建構在同源政策基礎之上的,浏覽器隻是針對同源政策的一種實作。
同源:協定、域名、端口,三者全部相同,才是同源。
跨域:協定、域名、端口,隻要有一個的不同,就是跨域。
服務端請求服務端不存在跨域(浏覽器請求伺服器才存在同源政策)
<code><img src="跨域的圖檔位址"></code> (<code><img></code>标簽的 <code>src</code> 屬性不存在跨域)
<code><link href="跨域的css位址"></code> (<code><link></code>标簽的 <code>href</code> 屬性不存在跨域)
<code><script src="跨域的js位址"></script></code> (<code><script></code>标簽的 <code>src</code> 屬性不存在跨域)
jsonp 跨域 (動态添加<code><script></code>标簽,利用src屬性跨域。 常用)
CORS 跨域資源共享(由服務端實作。 常用且主流)
node 代理跨域(利用<code>proxyTable</code>使本地的node伺服器代理請求真正的伺服器。 常用)
document.domain + iframe 跨域
postMessage 跨域
XSS 跨站腳本攻擊
CSRF 跨站請求僞造
淺談 HTTP
HTTP協定是一個基于 <code>TCP/IP</code> 通信協定來傳遞資料(HTML 檔案, 圖檔檔案, 查詢結果等),用于從伺服器傳輸超文本到本地浏覽器的傳送協定。
TCP的三次握手四次揮手
HTTP是無連接配接的:無連接配接的含義是限制每次連接配接隻處理一個請求。伺服器處理完客戶的請求,并收到客戶的應答後,即斷開連接配接。采用這種方式可以節省傳輸時間。
HTTP是媒體獨立的:這意味着,隻要用戶端和伺服器知道如何處理的資料内容,任何類型的資料都可以通過HTTP發送。用戶端以及伺服器指定使用适合的MIME-type内容類型。
HTTP是無狀态的:無狀态是指協定對于事務處理沒有記憶能力。缺少狀态意味着如果後續處理需要前面的資訊,則它必須重傳,這樣可能導緻每次連接配接傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。
用戶端請求消息(Request Headers):
用戶端發送一個HTTP請求到伺服器的請求消息包括以下格式:請求行(request line)、請求頭部(header)、空行和請求資料四個部分組成,下圖給出了請求封包的一般格式。
伺服器響應消息(Response Headers):
HTTP響應也由四個部分組成,分别是:狀态行、消息報頭、空行和響應正文。
HTTP狀态碼詳解
RFC 規定 HTTP 的狀态碼為三位數,被分為五類:
1xx: 資訊,伺服器收到請求,需要請求者繼續執行操作
2xx: 成功,操作被成功接收并處理 (200 - 請求成功)
3xx: 重定向,需要進一步的操作以完成請求(302 - 資源(網頁等)被臨時轉移到其它URL,浏覽器自動處理)
4xx: 用戶端錯誤,請求包含文法錯誤或無法完成請求(404 - 請求的資源(網頁等)不存在)
5xx: 伺服器錯誤,伺服器在處理請求的過程中發生了錯誤(500 - 内部伺服器錯誤)
GET和POST最詳細的總結
方法
協定版本
描述
GET
HTTP1.0
請求指定的頁面資訊,并傳回實體主體。(擷取資料)
HEAD
類似于 GET 請求,隻不過傳回的響應中沒有具體的内容,用于擷取報頭。
POST
向指定資源送出資料進行處理請求(例如送出表單或者上傳檔案)。資料被包含在請求體中。POST 請求可能會導緻新的資源的建立和/或已有資源的修改。(建立資料)
PUT
HTTP1.1
從用戶端向伺服器傳送的資料取代指定的文檔的内容。
DELETE
請求伺服器删除指定的頁面。(删除資料)
CONNECT
預留給能夠将連接配接改為管道方式的代理伺服器。
OPTIONS
允許用戶端檢視伺服器的性能。
TRACE
回顯伺服器收到的請求,主要用于測試或診斷。
PATCH
是對 PUT 方法的補充,用來對已知資源進行局部更新 。(更新資料)
一文讀懂http緩存(超詳細)
當用戶端向伺服器請求資源時,會先抵達浏覽器緩存,如果浏覽器有“要請求資源”的副本,就可以直接從浏覽器緩存中提取而不是從原始伺服器中提取這個資源。
常見的http緩存隻能緩存get請求響應的資源,對于其他類型的響應則無能為力。
緩存的優點:
減少了備援的資料傳輸,節省了你的網絡費用。
緩解了網絡瓶頸的問題。不需要更多的帶寬就能夠更快地加載頁面。
降低了對原始伺服器的要求。伺服器可以更快地響應,避免過載的出現。
降低了距離時延,因為從較遠的地方加載頁面會更慢一些。
強緩存與協商緩存:
第一次請求資源時,伺服器傳回資源,并在<code>respone header</code>中回傳資源和資源辨別(<code>Last-Modified</code>、<code>Etag</code>)。
第二次請求資源時,浏覽器會判斷 <code>response headers</code> 是否命中(<code>cache-control屬性</code>)強緩存,如果命中,直接從本地讀取緩存(狀态碼200),不會向伺服器發送請求。
當強緩存沒有命中時,就把請求參數(含<code>If-Modified-Since</code>、<code>If-Not-Match</code>)加到 <code>request header</code> 頭中傳給伺服器,判斷協商緩存是否命中,如果命中(<code>If-Modified-Since == Last-Modified</code>、<code>If-Not-Match == Etag</code>)則伺服器将請求傳回(狀态碼304),不會傳回資源,告訴浏覽器從本地讀取緩存。
當協商緩存沒有命中(<code>If-Modified-Since != Last-Modified</code>、<code>If-Not-Match != Etag</code>)時,伺服器直接傳回新的資源(狀态碼200)和新的資源辨別(新的<code>Last-Modified</code>、新的<code>Etag</code>) 。
資源辨別:
Last-Modified:資源的最後修改時間(隻能精确到秒級)
Etag:資源的唯一辨別,會優先使用(一個字元串,類似人類的指紋)
如果資源被重複生産,而内容不變,則 Etag 更精準
差別:
強緩存命中:不會請求伺服器,直接請求緩存;(非常快)
協商緩存命中:會請求伺服器,不會傳回内容,然後讀取緩存;(服務端緩存政策)
手寫常見JS方法
判斷資料類型
深拷貝
對象是否全等
防抖
節流
數組拍平
數組去重
new函數
Git詳細教程
項目常用指令:
擷取IP位址
TCP/IP三次握手建立連接配接
浏覽器向web伺服器發送http請求
浏覽器渲染
四次揮手斷開連接配接
DOM 樹:解析 HTML 建構 DOM(DOM 樹)
CSS 樹:解析 CSS 建構 CSSOM(CSS 樹)
渲染樹:CSSOM 和 DOM 一起生成 Render Tree(渲染樹)
布局(layout):根據Render Tree浏覽器就知道網頁中有哪些節點,以及各個節點與 CSS 的關系,進而知道每個節點的位置和幾何屬性(重排)
繪制(Paint):根據計算好的資訊繪制整個頁面(重繪)
vue 3.0 超詳細入門教程
對MVVM的了解
MVVM 分為 <code>Model</code> 、 <code>View</code> 、 <code>ViewModel</code> 三者:
<code>Model</code>:資料層,資料和業務邏輯都在Model層中定義。
<code>View</code>:視圖層,也就是使用者界面,負責資料的展示。
<code>ViewModel</code>:視圖資料層, ViewModel層通過雙向資料綁定将View層和Model層連接配接了起來(View和Model層的橋梁),使得View層和Model層的同步工作完全是自動的。
Model和View并無直接關聯,而是通過ViewModel這個橋梁來進行聯系的,ViewModel就是View與Model的連接配接器,View與Model通過ViewModel實作雙向綁定。
beforeCreate:建立之前(<code>el</code>、<code>data</code>和<code>message</code>都還是<code>undefined</code>,不可用的)
created:建立完畢(能讀取到資料<code>data</code>的值,但是<code>DOM</code>還沒生成)
beforeMount:挂載之前(生成<code>DOM</code>,但此時<code>{{ message }}</code>還沒有挂載<code>data</code>中的資料)
mounted:挂載完畢(<code>{{ message }}</code>已經成功挂載渲染<code>data</code>的值)
beforeUpdate:更新之前
updated:更新完畢
beforeDestroy:銷毀之前
destroyed:銷毀完畢(執行個體與視圖的關系解綁,再修改<code>message</code>的值,視圖再也不會更新了)
activated:<code>keep-alive</code> 元件激活時調用
deactivated:<code>keep-alive</code> 元件停用時調用
注:
<code>activated</code> 和 <code>deactivated</code> 是比較特殊的兩個鈎子,需要<code>keep-live</code>配合使用
當引入 <code>keep-alive</code> 的時候,頁面第一次進入,鈎子的觸發順序 <code>created</code> => <code>mounted</code> => <code>activated</code>,退出時觸發 <code>deactivated</code>。當再次進入(前進或者後退)時,隻觸發<code>activated</code>。
onBeforeMount
onMounted
onBeforeUpdate
onUpdated
onBeforeUnmount
onUnmounted
onActivated
onDeactivated
onErrorCaptured
onRenderTracked
onRenderTriggered
Vue中computed與watch
屬性的結果會被緩存(預設走緩存),當<code>computed</code>中的函數所依賴的屬性沒有發生改變的時候,那麼調用目前函數的時候結果會從緩存中讀取,除非依賴的響應式屬性變化時才會重新計算;
不支援異步,當<code>computed</code>内有異步操作時無效,無法監聽資料的變化;
<code>computed</code>中的函數必須用<code>return</code>傳回最終的結果。<code>computed</code>更高效,優先使用;
當一個屬性受多個屬性影響的時候,一般用<code>computed</code>(例如:詳細位址 = 省+市+區+街道+樓棟+房号 );
不支援緩存,資料變,直接會觸發相應的操作;
支援異步;
監聽的函數接收兩個參數,第一個參數是最新的值(newVal);第二個參數是輸入之前的值(oldVal);
當一條資料影響多條資料的時候,一般使用<code>watch</code>(例如:搜尋資料(異步) ,觸發一系列資料的變化);
是通過控制 DOM 元素的存在與否來控制元素的顯隐;
切換時,是對 DOM 元素進行一個建立和銷毀的動作;
是惰性的,如果初始條件為假,則什麼也不做;隻有在條件第一次變為真時才開始局部編譯;
有更高的切換消耗;
是通過設定 DOM 元素的 <code>display</code> 樣式,<code>block</code> 為顯示,<code>none</code> 為隐藏;
切換時,隻是簡單的基于CSS切換;
是在任何條件下(首次條件是否為真)都被編譯,然後被緩存,而且 DOM 元素保留;
有更高的初始渲染消耗;
基于以上差別,是以,如果需要非常頻繁地切換,則使用 <code>v-show</code> 較好;如果在運作時條件很少改變,則使用 <code>v-if</code> 較好。
如果 Vue 元件中的 data 是個對象,那麼就像所有複用這個元件的地方,都在使用這個元件裡面唯一的一個 data,所有使用元件的地方的 data 都會指向棧内這一個 data 的位址,那麼會造成一個改 data 的值,所有其他元件的 data 都會被改變。
如果在函數中傳回一個對象,那麼在每次建立一個元件的時候,每次傳回的都是一個新對象(Object的執行個體),在記憶體中同時開辟一塊空間給目前元件存放 data 。這樣就不會出現共用一個 data 的現象
Vue中的diff算法
diff 算法是一種優化手段。比如有時候我們修改了某個資料,如果直接渲染到真實 DOM 上會引起整個 DOM 樹的重繪和重排,這樣開銷是非常大的。
我們可以先根據真實 DOM 生成一棵虛拟DOM(virtual DOM)樹,當虛拟DOM某個節點的資料改變後,會生成一個新的 <code>Vnode</code>(虛拟節點)。然後 <code>Vnode</code> 和 <code>oldVnode</code> 作對比,發現有不一樣的地方就直接修改在真實的 DOM 上,然後使 <code>oldVnode</code> 的值為<code>Vnode</code>。此時我們隻更新我們修改的那一小塊 DOM,而不要更新整個 DOM。
diff的過程就是調用patch函數,比較新舊節點,一邊比較一邊給真實的DOM打更新檔。
在采取 diff 算法比較新舊節點的時候,比較隻會在同層級進行, 不會跨層級比較。
概括起來就是:對操作前後的 DOM 樹同一層的節點進行對比,一層一層對比,然後再插入真實的dom中,重新渲染。
vue中清單循環需加 <code>:key="唯一辨別"</code>, 唯一辨別可以是 <code>item</code> 裡面 <code>id</code>、 <code>index</code> 等。
key 的作用主要是為了更高效的對比虛拟DOM中每個節點是否是相同節點;
Vue 在 patch 過程中判斷兩個節點是否是相同節點, key 是一個必要條件,渲染一組清單時,key往往是唯一辨別,是以如果不定義 key 的話,Vue 隻能認為比較的兩個節點是同一個,哪怕它們實際上不是,這導緻了頻繁更新元素,使得整個 patch 過程比較低效,影響性能;
從源碼中可以知道,Vue 判斷兩個節點是否相同時主要判斷兩者的 key 和元素類型等,是以如果不設定 key ,它的值就是undefined,則可能永遠認為這是兩個相同的節點,隻能去做更新操作,這造成了大量的 DOM 更新操作,明顯是不可取的。
不建議 用 <code>index</code> 作為 <code>key</code>,和沒寫基本上沒差別,因為不管你數組的順序怎麼颠倒,<code>index</code> 都是 0, 1, 2 這樣排列,導緻 Vue 會複用錯誤的舊子節點,做很多額外的工作
當一個Vue執行個體建立時,Vue會周遊 data 選項的屬性,利用 <code>Object.defineProperty</code> 将它們轉為 <code>getter/setter</code> 并且在内部追蹤相關依賴,在屬性被通路和修改時通知變化。每個元件執行個體都有相應的 <code>watcher</code> 程式執行個體,它會在元件渲染的過程中把屬性記錄為依賴,之後當依賴項的 <code>setter</code> 被調用時,會通知 <code>watcher</code> 重新計算,進而緻使它關聯的元件得以更新。
極簡版雙向綁定:
vue 中雙向綁定是一個指令<code>v-model</code>,可以綁定一個動态值到視圖,同時視圖中變化能改變該值。
<code>v-model</code> 是文法糖,預設情況下相于<code>:value</code>和<code>@input</code>:
Vue元件通信方式總結
新建立一個 <code>event-bus.js</code> 檔案
A 頁面發送資料
B 頁面接收資料
移除事件監聽
vuex詳解
state:定義了應用狀态的資料結構,可以在這裡設定預設的初始狀态。
getter:可以認為是 <code>store</code> 的計算屬性(有緩存,隻有當它的依賴值發生了改變才會被重新計算)。
mutation:是唯一更改 <code>store</code> 中狀态的方法,且必須是同步函數。
action:用于送出 <code>mutation</code>(再由<code>mutation</code>更改 <code>store</code> 中狀态),而不是直接變更狀态,可以包含任意異步操作。
module:可以将 store 分割成子產品(module)。每個子產品擁有自己的 <code>state</code>、<code>mutation</code>、<code>action</code>、<code>getter</code>、甚至是嵌套子子產品
基本用法:
module 用法
Vue路由導航 router-link 和 router.push
1. 不攜帶參數
2. 通過 <code>query</code> 攜帶參數:
位址欄變成 <code>/login?color=red</code>
可通過 <code>{{$route.query.color}}</code> 或 <code>this.$route.query.color</code> 擷取參數
3. 通過 <code>params</code> 攜帶參數:
位址欄變成 <code>/login/red</code>
可通過 <code>{{$route.params.color}}</code> 或 <code>this.$route.params.color</code> 擷取參數
此時 <code>router.js</code> 中需要設定 <code>path: '/login/:color?'</code>
<code>$router</code> :是指整個路由執行個體,你可以操控整個路由,用法如下:
<code>$route</code>:是指目前路由執行個體<code>$router</code>跳轉到的路由對象;路由執行個體可以包含多個路由對象,它們是父子包含關系
router.js相關配置
路由懶加載的不同寫法:
webpack < 2.4版(vue-cli2)的懶加載
webpack > 2.4版(vue-cli3)的懶加載