@(目錄) 點擊打開視頻講解面試技巧+面試全過程 一、HTML 1、語義話的目的是什麼? 語義化的主要目的可以概括為用正確的標簽做正確的事 HTMl語義化可以讓頁面的內容結構化,以便於瀏覽器解析和搜索引擎解析, 並且提高了代碼的可讀性便於代碼維護, 2、HTML5新增元素 Canvas繪圖以及SVG ...
@
目錄- 一、HTML
- 二、CSS
- 三、JS
- 1、什麼是閉包?
- 2、call、apply、bind 作用和區別(改變this指向)
- 3、原型與原型鏈
- 4、JS基本數據類型
- 5、export和export default的區別
- 6、箭頭函數和普通函數的區別
- 7、GET和POST的區別
- 8、forEach和map的區別
- 9、對象的繼承
- 10、簡述一下你理解的面向對象
- 11、 == 和 ===的區別
- 12、數組有哪些方法?
- 13、 數組去重(筆試一般都會有)
- 14、JS中new操作符有什麼用?
- 15、JS獲取HTML DOM元素的方法
- 16、事件捕獲和事件冒泡
- 17、虛擬dom
- 18、排序方式
- 19、數組操作方法會改變原數組
- 20、JS有幾種方法判斷變數的類型?
- 21、null和undefined的區別?
- 22、什麼是跨域?及跨域解決方法
- 23、防抖和節流的使用及區別
- 24、棧記憶體和堆記憶體的區別與原理
- 25、深拷貝和淺拷貝的區別和與原理
- 四、ES6新特性
- 五、電腦網路知識
- 六、VUE
- 1、MVC和MVVM的理解
- 2、數據雙向綁定原理
- 3、vue生命周期
- 4、為什麼使用虛擬DOM(常問)
- 5、v-if 和 v-show的作用和區別
- 5、用過vue的哪些組件?
- 6、vue-router 的模式有?
- 7、組件之間如何傳值
- 8、路由之間如何傳參
- 9、VUEX
- 10、如何解決vuex頁面刷新數據丟失問題?
- 11、computed和watch的區別?
- 12、route和router的區別
- 13、vue中數據變了但是視圖不跟新怎麼解決?
- 14、vue中data為什麼是函數而不是對象?
- 15、vue中父子組件傳值,父組件非同步請求,子組件不能實時更新怎麼解決?(vue中數據不能實時更新怎麼解決?)
- 16、Vue 路由跳轉方式
- 17、Vue 中 for迴圈為什麼加 key?
- 18、vue路由守衛有哪些?
- 19、vue常⽤的修飾符
- 20、vue的兩個核⼼點
- 21、delete和Vue.delete刪除數組的區別
- 22、vue常⽤的UI組件庫
- 23、Vue首頁白屏是什麼問題引起的?如何解決呢?
- 24、性能優化篇
- 七、React
點擊打開視頻講解面試技巧+面試全過程
一、HTML
1、語義話的目的是什麼?
語義化的主要目的可以概括為用正確的標簽做正確的事
HTMl語義化可以讓頁面的內容結構化,以便於瀏覽器解析和搜索引擎解析,
並且提高了代碼的可讀性便於代碼維護,
2、HTML5新增元素
Canvas繪圖以及SVG繪圖。
拖放(Drag and drop)API
語義化標簽(header、nav、footer、article、section)
音頻、視頻(audio、video)API
地理定位(Geolocation)
本地離線存儲(localStorage),長期存儲數據,關閉瀏覽器後不丟失。
會話儲存(sessionStorage),數據在關閉瀏覽器後自動刪除。
表單控制項(calendar、date、time、email、url、search)
3、cookie與sessionStorage和localStorage的區別
保存方式
cookie存放在客戶的瀏覽器上。
session都在客戶端中保存,不參與伺服器通訊。
生命周期
cookie可設置失效時間
localStorage除非手動清除否則永久保存
sessionStorage關閉當前頁面或瀏覽器後失效
存儲的大小
cookie 4kb左右
session 5M
易用性
cookie需自己封裝
session可以接受原生介面
因為cookie每次請求都會攜帶在http請求中,所以它的主要用來識別用戶登錄,localStorage可以用
來跨頁面傳參,sessionStorage可以用來保留一些臨時數據。
二、CSS
1、CSS有哪些基本的選擇器,執行先後順序?
id選擇器 => #myId {}
類選擇器 => .myClass {}
標簽選擇器 => p,h1 {}
後代選擇器 => div h1 {}
子選擇器 => div>h1 {}
兄弟選擇器(所有的兄弟) => ul~h1 {}
相鄰兄弟選擇器 => ul+h1 {}
屬性選擇器 => li[name='sss'] {}
偽類選擇器 => h1:hover {}
偽元素選擇器 => h1::before{}
通配符選擇器* => * {}
!important>內聯樣式(非選擇器)>ID選擇器>類選擇器>標簽選擇器>通配符選擇器(*)
2、垂直水平居中方式有哪些?
3、常用佈局方式有哪些?什麼是盒模型?
4、常用的塊元素與行內元素有哪些?有什麼特征
塊元素:div、h1~h6、ul、li、table、p、br、form。
特征:獨占一行,換行顯示,可以設置寬高,可以嵌套塊和行
行內元素:span、a、img、textarea、select、option、input。
特征:只有在行內顯示,內容撐開寬、高,不可以設置寬、高(img、input、textarea等除外)。
5、清除浮動
父級div定義overflow:hidden(如果父級元素有定位元素超出父級,超出部分會隱藏,)
給浮動元素父級增加標簽(由於新增標簽會造成不必要的渲染,不建議使用)
偽元素清除浮動:給浮動元素父級增加 .clearfix::after(content: ‘’; display: table;
clear: both;)(不會新增標簽,不會有其他影響,)
6、CSS3新特征
圓角(border-radius)
陰影(box-shadow)
文字特效(text-shadow)
線性漸變(gradient)
變換(transform)
更多的CSS選擇器
更多背景設置(background)
色彩模式(rgba)
偽元素(::selection)
媒體查詢(@media)
多欄佈局(column)
圖片邊框(border-image)
7、CSS中有哪些長度單位?
絕對長度單位:px
百分比: %
相對父元素字體大小單位: em
相對於根元素字體大小的單位: rem
相對於視口*寬度的百分比(100vw即視窗寬度的100%): vw
相對於視口*高度的百分比(100vh即視窗高度的100%): vh
8、px、em、rem的區別
9、display:none和visibility:hidden的區別
display:none:隱藏元素,在文檔佈局中不在給它分配空間(從文檔中移除),會引起迴流(重排)
visibility:hidden: 隱藏元素,但是在文檔佈局中仍保留原來的空間(還在文檔中),
不會引起迴流(重繪)
10、用CSS 實現三角形
11、偽類和偽元素的區別
12、什麼是重繪,重排?如何解決?
重繪(repaint/redraw)
某個dom節點的顏色,背景顏色變了,字體大小,隻影響自己,不影響其他元素。
註意:table及其內部元素可能需要多次計算才能確定好其在渲染樹中節點的屬性,比同等元素要多花兩倍時間,這就是我們儘量避免使用table佈局頁面的原因之一。
重排(迴流/reflow/重構)
某個dom節點的寬高,佈局,隱藏等發生改變,不僅自身發生了改變,而且其他元素也會受到影響隨之發生改變。每個頁面最少一次迴流,就是頁面第一次載入的時候。
觸發重排的原因
頁面初始化渲染(無可避免)
添加或刪除可見的DOM元素
元素尺寸的改變------大小,外邊距;邊框
瀏覽器視窗尺寸的變化
填充內容的改變,比如文本的改變或圖片大小改變而引起的計算值寬度和高度的改變
讀取某些元素屬性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height,
scrollTop/Left/Width/Height, width/height, getComputedStyle(),
currentStyle(IE) )
1.重繪不一定重排,但是重排一定會重繪
2.重繪和重排的成本都是非常高的,要儘量減少dom的增刪改
如何解決
不要直接操作樣式,先設置好class,然後修改DOM的className;
position:absolute 與flex 不會導致重排
不要把DOM 節點的屬性放在一個迴圈當成迴圈的變數;
需要動畫的元素脫離文檔流;
不使用table 佈局,
儘量不修改影響範圍比較大的DOM;
如果要多次添加DOM,先使用 document.createDocumentFragment() 創建一個盒子,
完盒子裡面先添加子元素,添加完成在插入元素中;
13、transition 都有哪些過度屬性?
14、link和@import的區別?
link屬於html標簽,而@import是css提供的。
頁面被載入時,link會同時被載入,而@import引用的css會等到頁面被載入完再載入的。
相容性問題:@import只在IE5以上才能識別,而link是html標簽,無相容性問題。
權重問題:@import的權重要高於link。
DOM操作:DOM可以操作link中的樣式,而不可以操作@import中的樣式。
<!-- html 文件 -->
<!-- link 方式,推薦 -->
<link rel="stylesheet" type="text/css" href="style.css" media="screen" />
<!-- @import 方式 -->
<style type="text/css" media="screen">
@import url(style.css);
</style>
15、常用的動畫庫有哪些?
16、什麼是BFC
17、href與src的區別
18、如何讓 CSS 只在當前組件中起作用?
將當前組件的<style>修改為<style scoped>。
三、JS
1、什麼是閉包?
2、call、apply、bind 作用和區別(改變this指向)
3、原型與原型鏈
4、JS基本數據類型
5、export和export default的區別
6、箭頭函數和普通函數的區別
- 語法更加簡潔、清晰,=>()
- 箭頭函數是匿名函數,不能作為構造函數,不能使用new
- 箭頭函數不能使用arguments,而用reat參數…解決
- 箭頭函數沒有自己的this,會捕獲其所在的上下文的this值,並且不能通過call()和apply()來改變其this
- 箭頭函數沒有原型
7、GET和POST的區別
8、forEach和map的區別
9、對象的繼承
常見的:
原型鏈繼承
借用構造函數繼承
原型鏈+借用構造函數的組合繼承(使用 call 或 applay 方法)
ES6中class 的繼承(class可以通過extends關鍵字實現繼承)
10、簡述一下你理解的面向對象
面向對象是基於萬物皆對象這個哲學觀點. 把一個對象抽象成類,具體上就是把一個對象的靜態特征和動態特征抽象成屬性和方法,也就是把一類事物的演算法和數據結構封裝在一個類之中,程式就是多個對象和互相之間的通信組成的。
面向對象具有封裝性,繼承性,多態性。
封裝:隱蔽了對象內部不需要暴露的細節,使得內部細節的變動跟外界脫離,只依靠介面進行通信.封裝性降低了編程的複雜性。
繼承:使得新建一個類變得容易,一個類從派生類那裡獲得其非私有的方法和公用屬性的繁瑣工作交給了編譯器。
多態:繼承和實現介面和運行時的類型綁定機制所產生的多態,使得不同的類所產生的對象能夠對相同的消息作出不同的反應,極大地提高了代碼的通用性.。
11、 == 和 ===的區別
12、數組有哪些方法?
13、 數組去重(筆試一般都會有)
14、JS中new操作符有什麼用?
- 創建臨時對象,並將this指向臨時對象
- 將構造函數的原型屬性和方法掛載到新對象的__proto__(原型指針)上
- return 臨時對象
15、JS獲取HTML DOM元素的方法
- 通過ID獲取(getElementById)
- 通過name屬性(getElementsByName)
- 通過標簽名(getElementsByTagName)
- 通過類名(getElementsByClassName)
- 獲取html的方法(document.documentElement)
- 獲取body的方法(document.body)
- 通過選擇器獲取一個元素(querySelector)
- 通過選擇器獲取一組元素(querySelectorAll)
16、事件捕獲和事件冒泡
- 事件捕獲和事件冒泡主要解決了頁面事件流的問題。頁面的事件流經過了三個階段,分別是事件捕獲、目標階段和事件冒泡階段。
- 事件捕獲是由外向內;而事件冒泡則是由內向外。
- event.stopPropagation() 可以阻止事件流的進一步傳播。
- 採用事件代理的方式,能夠節省記憶體消耗,對於動態改變子元素的時候,也非常有利,避免了很多麻煩的步驟,比如重新綁定事件。(把子元素的事件委托給父元素來處理)
17、虛擬dom
定義: 虛擬DOM就是普通的js對象。用來描述真實dom結構的js對象,因為它不是真實的dom,所以才叫做虛擬dom。
作用: 虛擬dom可以很好地跟蹤當前dom狀態,因為它會根據當前數據生成一個描述當前dom結構的虛擬dom,然後數據發生變化時,有生成一個新的虛擬dom,而兩個虛擬dom恰好保存了變化前後的狀態。然後通過diff演算法,計算出當前兩個虛擬dom之間的差異,得出一個更好的替換方案。
18、排序方式
冒泡排序:比較所有相鄰元素,如果第一個比第二個大,則交換它們。
選擇排序:找到數組中的最小值,選中它並將其放置在第一位。
插入排序:從第二個數開始往前比,比它大就往後排。
歸併排序:把數組劈成兩半,再遞歸地對數組進行“分”操作,直到分成一個個單獨的數。
快速排序:從數組中任意選擇一個基準,所有比基準小的元素放到基準前面,比基準大的元素放到
基準的後面。
19、數組操作方法會改變原數組
會改變:push(),pop(),shift(),unshift() ,splice(),sort(),reverse()。
不變:concat(),split(),slice()。
js中substr()、substring()、slice()、splice()、split()的區別與作用
20、JS有幾種方法判斷變數的類型?
typeof:判斷基本數據類型,對於引用數據類型除了function返回’function‘,其餘全部
返回’object’。
instanceof:區分引用數據類型,檢測方法是檢測的類型在當前實例的原型鏈上,用其檢測出來的
結果都是true,不太適合用於簡單數據類型的檢測,檢測過程繁瑣且對於簡單數據類
型中的undefined, null, symbol檢測不出來。
constructor:檢測引用數據類型,檢測方法是獲取實例的構造函數判斷和某個類是否相同,如果
相同就說明該數據是符合那個數據類型的,這種方法不會把原型鏈上的其他類也加入
進來,避免了原型鏈的干擾。
Object.prototype.toString.call():適用於所有類型的判斷檢測,檢測方法是
Object.prototype.toString.call(數據) 返回的是該數據類型的字元串。
(舉例:字元串返回的是[object String])
instanceof的實現原理:驗證當前類的原型prototype是否會出現在實例的原型鏈__proto__上,只要在它的原型鏈上,則結果都為true。因此,instanceof 在查找的過程中會遍歷左邊變數的原型鏈,直到找到右邊變數的 prototype,找到返回true,未找到返回false。
Object.prototype.toString.call原理:Object.prototype.toString 表示一個返回對象類型的字元串,call()方法可以改變this的指向,那麼把Object.prototype.toString()方法指向不同的數據類型上面,返回不同的結果
21、null和undefined的區別?
null和undefined 區別為:undefined是表示變數聲明過但並未賦過值,它是所有未賦值變數預設值;null表示一個變數將來可能指向一個對象,一般用於主動釋放指向對象的引用。
(1)、null與undefined的異同點是什麼呢?
共同點: 都是原始類型,保存在棧中變數本地
不同點:
(1)undefined——表示變數聲明過但並未賦過值。
它是所有未賦值變數預設值。
例如:var a; //a自動被賦值為undefined
(2)null——表示一個變數將來可能指向一個對象。
一般用於主動釋放指向對象的引用。
2、何時使用null?
當使用完一個比較大的對象時,需要對其進行釋放記憶體時,設置為null
3、定義
(1)undefined:是所有沒有賦值變數的預設值,自動賦值
(2)null:主動釋放一個變數引用的對象,表示一個變數不再指向任何對象地址
22、什麼是跨域?及跨域解決方法
23、防抖和節流的使用及區別
24、棧記憶體和堆記憶體的區別與原理
25、深拷貝和淺拷貝的區別和與原理
四、ES6新特性
新增塊級作用域let定義變數和const定義常量
變數的解構賦值
模板字元串 (‘${}’)
預設參數(key=value)
箭頭函數(=>)
擴展運算符(…)
模塊(import/export)
類(class/extends)
Promise
Proxy
Symbol
Promise
含義: 非同步編程的一種解決方案,用來解決回調地獄。
三種狀態: pending(進行中)、fulfilled(已成功)和rejected(已失敗) (Promise對象的狀態改變,只有兩種可能:從pending變為fulfilled和從pending變為rejected。)
resolved函數作用: 將Promise對象的狀態從“未完成”變為“成功”(即從 pending 變為 resolved)。
reject函數的作用: 將Promise對象的狀態從“未完成”變為“失敗”(即從 pending 變為 rejected)。
Promise實例生成以後,可以用then方法分別指定resolved狀態和rejected狀態的回調函數。
then: Promise 實例添加狀態改變時的回調函數。可以接受兩個回調函數作為參數。第一個回調函數是Promise對象的狀態變為resolved時調用,第二個回調函數是Promise對象的狀態變為rejected時調用。
缺點: 無法取消Promise,一旦新建它就會立即執行,無法中途取消。如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。
五、電腦網路知識
1、HTTP與HTTPS
HTTP:客戶端與伺服器之間數據傳輸的格式規範,表示“超文本傳輸協議”。
HTTPS:在HTTP與TCP之間添加的安全協議層。
預設埠號:HTTP:80,HTTPS:443。
傳輸方式:http是明文傳輸,https則是具有安全性的ssl加密傳輸協議。
連接方式:http的是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證
的網路協議,比http協議安全。
2、TCP與UDP的區別
TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發送數據之前不需要建立連接。
TCP面向位元組流,實際上是TCP把數據看成一連串無結構的位元組流;UDP是面向報文的
每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信
TCP首部開銷20位元組;UDP的首部開銷小,只有8個位元組。
TCP提供可靠的服務。UDP適用於一次只傳少量數據、對可靠要求不高的環境。
3、HTTP常見的狀態碼
1開頭的狀態碼(信息類)
100,接受的請求正在處理,信息類狀態碼
2開頭的狀態碼(成功類)
2xx(成功)表示成功處理了請求的狀態碼
200(成功)伺服器已成功處理了請求。
3開頭的狀態碼(重定向)
3xx(重定向)表示要完成請求,需要進一步操作。通常這些狀態代碼用來重定向。
301,永久性重定向,表示資源已被分配了新的 URL
302,臨時性重定向,表示資源臨時被分配了新的 URL
303,表示資源存在另一個URL,用GET方法獲取資源
304,(未修改)自從上次請求後,請求網頁未修改過。伺服器返回此響應時,不會返回網頁內容
4開頭的狀態碼(客戶端錯誤)
4xx(請求錯誤)這些狀態碼表示請求可能出錯,妨礙了伺服器的處理
400(錯誤請求)伺服器不理解請求的語法
401表示發送的請求需要有通過HTTP認證的認證信息
403(禁止)伺服器拒絕請求
404(未找到)伺服器找不到請求網頁
5開頭的狀態碼(伺服器錯誤)
5xx(伺服器錯誤)這些狀態碼表示伺服器在嘗試處理請求時發生內部錯誤。這些錯誤可能是伺服器
本身的錯誤,而不是請求的錯誤
500,(伺服器內部錯誤)伺服器遇到錯誤,無法完成請求
503,表示伺服器處於停機維護或超負載,無法處理請求
4、瀏覽器從輸入url到頁面載入發生了什麼
1、瀏覽器的地址欄輸入URL並按下回車。
2、瀏覽器查找當前URL是否存在緩存,並比較緩存是否過期。
3、DNS解析URL對應的IP。
4、根據IP建立TCP連接(三次握手)。
5、HTTP發起請求。
6、伺服器處理請求,瀏覽器接收HTTP響應。
7、渲染頁面,構建DOM樹。
8、關閉TCP連接(四次揮手)。
5、HTTP 傳輸過程
含義:從建立連接到斷開連接一共七個步驟,就是三次招手四次揮手
TCP 建立連接
瀏覽器發送請求命令
瀏覽器發送請求頭
伺服器應答
伺服器回應信息
伺服器發送數據
斷開TCP連接
6、瀏覽器如何渲染頁面的?
瀏覽器解析html源碼,將HTML轉換成dom樹,
將CSS樣式轉換成stylesheet(CSS規則樹),
瀏覽器會將CSS規則樹附著在DOM樹上,並結合兩者生成渲染樹(Render Tree)
生成佈局(flow),瀏覽器通過解析計算出每一個渲染樹節點的位置和大小,在屏幕上畫出渲染樹的
所有節點
合成繪製生成頁面。
7、性能優化
減少http請求次數
減少DNS查找
避免重定向
使用Ajax緩存
少用全局變數、減少DOM操作的使用
優化圖片大小,通過CSS Sprites(精靈圖)優化圖片,
將css放在頂部,將js放在底部
8、webpack是怎麼打包的,babel又是什麼
Webpack:把所有依賴打包成一個 bundle.js文件,通過代碼分割成單元片段並按需載入。Webpack是以公共JS的形式來書寫腳本的,但對AMD/CMD的支持也很全面,方便舊項目進行代碼遷移。
把項目當做一個整體,通過一個給定的主文件(如:index.js),Webpack將從這個文件開始找到項目的所有依賴文件,使用loaders處理它們,最後打包為一個(或多個)瀏覽器可識別的JavaScript文件。
babel將es6、es7、es8等語法轉換成瀏覽器可識別的es5或es3語法。
9、git 和 svn的區別
SVN是集中式版本控制系統,版本庫是集中放在中央伺服器的,首先要從中央伺服器哪裡得到最新的版本,幹完活後,需要把自己做完的活推送到中央伺服器。集中式版本控制系統是必須聯網才能工作(如果在區域網還可以,帶寬夠大,速度夠快,如果在互聯網下,如果網速慢的話,就納悶了)
Git是分散式版本控制系統,沒有中央伺服器的,每個人的電腦就是一個完整的版本庫,這樣,工作的時候就不需要聯網了,因為版本都是在自己的電腦上。自己在電腦上改了文件A,其他人也在電腦上改了文件A,這時,只需把各自的修改推送給對方,就可以互相看到對方的修改了。
10、webSocket
webSocket: 可以讓伺服器主動向客戶端發送消息,適合開發聊天室,多人游戲等協作應用。
WebSocket協議是基於TCP的一種新的網路協議。在 WebSocket API 中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,併進行雙向數據傳輸。
11、require和import區別
-
調用時間
require運行時調用,理論上可以運用在代碼任何地,甚至不需要賦值給某個變數之後再使用。
lmport是編譯時候調用,必須放在文件開頭,而且使用格式也是確定的。 -
遵循規範
require 是 AMD規範引入方式
import是es6的一個語法標準,如果要相容瀏覽器的話必須轉化成es5的語法 -
本質
require是賦值過程,其實require 的結果就是對象、數字、字元串、函數等,再把require的結果賦值給某個變數。
import是解構過程。
通過require 引入基礎數據類型時,屬於複製該變數。
通過require 引入複雜數據類型時,數據淺拷貝該對象。
出現模塊之間的迴圈引用時,會輸出已經執行的模塊,而未執行的模塊不輸出(比較複雜)。CommonJS模塊預設export的是一個對象,即使導出的是基礎數據類型。
ES6 模塊語法是 JavaScript 模塊的標準寫法,堅持使用這種寫法,取代 Node.js 的 CommonJS 語法。
使用import取代require()。
// CommonJS 的寫法
const moduleA = require('moduleA');
const func1 = moduleA.func1;
const func2 = moduleA.func2;
// ES6 的寫法
import { func1, func2 } from 'moduleA';
使用export取代module.exports。
// commonJS 的寫法
var React = require('react');
var Breadcrumbs = React.createClass({
render() {
return <nav />;
}
});
module.exports = Breadcrumbs;
// ES6 的寫法
import React from 'react';
class Breadcrumbs extends React.Component {
render() {
return <nav />;
}
};
export default Breadcrumbs;
12、事件迴圈(Event Loop)
原因:JavaScript是單線程,所有任務需要排隊,前一個任務結束,才會執行後一個任務。
所有任務可以分成兩種,一種是同步任務(synchronous),另一種是非同步任務(asynchronous)。
同步任務:在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務;
非同步任務:不進入主線程、而進入"任務隊列"的任務,只有"任務隊列"通知主線程,某個非同步任務可以執行了,該任務才會進入主線程執行。
同步和非同步任務分別進入不同的執行環境, 先執行同步任務,把非同步任務放入迴圈隊列當中掛起,等待同步任務執行完,再執行隊列中的非同步任務。非同步任務先執行微觀任務,再執行巨集觀任務。一直這樣迴圈,反覆執行。
微任務:Promise.then、catch、finally、async/await。
巨集任務:整體代碼 Script、UI 渲染、setTimeout、setInterval、Dom事件、ajax事件。
巨集任務、微任務是怎麼執行的?
執行順序:先執行同步代碼,遇到非同步巨集任務則將非同步巨集任務放入巨集任務隊列中,遇到非同步微任務則將非同步微任務放入微任務隊列中,當所有同步代碼執行完畢後,再將非同步微任務從隊列中調入主線程執行,微任務執行完畢後再將非同步巨集任務從隊列中調入主線程執行,一直迴圈直至所有任務執行完畢。
13、什麼是單頁面應用(SPA)
一個系統只載入一次資源,之後的操作交互、數據交互是通過路由、ajax來進行,頁面並沒有刷新。
在一個頁面上集成多種功能,甚至整個系統就只有一個頁面,所有的業務功能都是它的子模塊,通過特定的方式掛接到主界面上。
優點:
- 前後端分離
- 良好的交互體驗——用戶不用刷新頁面,頁面顯示流暢
- 減輕伺服器壓力——伺服器只出數據
- 共用一套後端代碼——多個客戶端可共用一套後端代碼
- 載入速度快,內容的改變不需要重新載入整個頁面,對伺服器壓力小
缺點:
- SEO難度高——數據渲染在前端進行
- 頁面初次載入比較慢,頁面複雜提高很多
多頁面: 一個應用多個頁面,頁面跳轉時整個頁面都刷新,每次都請求一個新的頁面
有點:SEO效果好
缺點: 頁面切換慢,每次切換頁面需要選擇性的重新載入公共資源
14、什麼叫優雅降級和漸進增強?
漸進增強(Progressive Enhancement): 一開始就針對低版本瀏覽器進行構建頁面,完成基本的功能,然後再針對高級瀏覽器進行效果、交互、追加功能達到更好的體驗。
優雅降級(Graceful Degradation): 一開始就構建站點的完整功能,然後針對瀏覽器測試和修複。
在傳統軟體開發中,經常會提到向上相容和向下相容的概念。漸進增強相當於向上相容,而優雅降級相當於向下相容。向下相容指的是高版本支持低版本的或者說後期開發的版本支持和相容早期開發的版本,向上相容的很少。大多數軟體都是向下相容的。
二者區別:
1、優雅降級和漸進增強只是看待同種事物的兩種觀點。
2、優雅降級觀點認為應該針對那些最高級、最完善的瀏覽器來設計網站。
3、漸進增強觀點則認為應關註於內容本身。
六、VUE
1、MVC和MVVM的理解
M:model(數據模型),V:view(視圖),C:controller(邏輯處理),VM:(連接model和view)
MVC:單向通信。必須通過controller來承上啟下。
MVVM:數據雙向綁定,數據改變視圖,視圖改變數據。
2、數據雙向綁定原理
答:通過數據劫持結合發佈—訂閱模式,通過Object.defineProperty()為各個屬性定義get、set
方法,在數據發生改變時給訂閱者發佈消息,觸發相應的事件回調。
3、vue生命周期
Vue 實例有一個完整的生命周期,也就是從開始創建、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、卸載等一系列過程,我們稱這是 Vue 的生命周期。通俗說就是 Vue 實例從創建到銷毀的過程,就是生命周期。
- beforeCreate:創建前。此時,組件實例剛剛創建,還未進行數據觀測和事件配置,拿不到任何數據。
- created:創建完成。vue 實例已經完成了數據觀測,屬性和方法的計算(比如props、methods、data、computed和watch此時已經拿得到),未掛載到DOM,不能訪問到el屬性,el屬性,ref屬性內容為空數組常用於簡單的ajax請求,頁面的初始化。
- beforeMount:掛載前。掛在開始之前被調用,相關的render函數首次被調用(虛擬DOM)。編譯模板,把data裡面的數據和模板生成html,完成了el和data 初始化,註意此時還沒有掛在html到頁面上。
- mounted:掛載完成。也就是模板中的HTML渲染到HTML頁面中,此時可以通過DOM API獲取到DOM節點,$ref屬性可以訪問常用於獲取VNode信息和操作,ajax請求,mounted只會執行一次。
- beforeUpdate:在數據更新之前被調用,發生在虛擬DOM重新渲染和打補丁之前,不會觸發附加地重渲染過程。
- updated:更新後。在由於數據更改導致地虛擬DOM重新渲染和打補丁之後調用,
beforeDestroy;銷毀前。在實例銷毀之前調用,實例仍然完全可用。(一般在這一步做一些重置的操作,比如清除掉組件中的定時器 和 監聽的dom事件) - destroyed:銷毀後。在實例銷毀之後調用,調用後,vue實列指示的所有東西都會解綁,所有的事件監聽器會被移除。
其他:
activated:在keep-alive組件激活時調用
deactivated:在keep-alive組件停用時調用
4、為什麼使用虛擬DOM(常問)
- 創建真實DOM的代價高:真實的 DOM 節點 node 實現的屬性很多,而 vnode 僅僅實現一些必要的屬性,相比起來,創建一個 vnode 的成本比較低。
- 觸發多次瀏覽器重繪及迴流:使用 vnode ,相當於加了一個緩衝,讓一次數據變動所帶來的所有 node 變化,先在 vnode 中進行修改,然後 diff 之後對所有產生差異的節點集中一次對 DOM tree 進行修改,以減少瀏覽器的重繪及迴流。
- 虛擬dom由於本質是一個js對象,因此天生具備跨平臺的能力,可以實現在不同平臺的準確顯示。
- Virtual DOM 在性能上的收益並不是最主要的,更重要的是它使得 Vue 具備了現代框架應有的高級特性。
5、v-if 和 v-show的作用和區別
無論v-show的值為true或者false,元素都會存在於html頁面中; 而v-if的值為true時,元素才會
存在於html頁面中。
v-show指令是通過修改元素的display屬性來實現的。
v-if是動態地向DOM樹內添加或者刪除DOM元素,v-show是通過設置DOM元素的display樣式屬性控制
顯隱的。
v-if是"真正的"條件渲染,因為它會確保在奇幻過程中條件快內的事件監聽器和子組件適當的銷毀和
重建。
v-if也是惰性的,如果在初始渲染時條件為假,則什麼也不做,直到條件第一次變為真時,才開始渲染
條件塊。
v-show不管初始條件是什麼,元素總會背渲染,並且只是簡單地基於css進行切換。
一般來說,v-if有更高的切換開銷,而v-show則有更高的初始渲染開銷
因此,如果需要非常頻繁地切換,使用v-show比較好,如果在運行時條件不會改變時,用v-if比較好
切換時生命周期函數的執行
v-if
初始渲染
初始值為false時,不會渲染(所謂惰性),生命周期函數不會執行
初始值為true時,組件開始渲染,依次執行beforCreate,created,beforeMount,mounted等生命周期
切換時
從false到true:依次執行beforeCreate,created,beforeMount,moynted
從true到false:依次執行beforeDestroy,destroyed
v-show
初始渲染
無論初始狀態為true還是false,組件都會渲染,依次執行beforeCreate,created,beforeMount,mounted
切換
基於css進行切換,對生命周期函數無影響.
5、用過vue的哪些組件?
1、vue-route
2、axios
3、vuex
4、Element UI
5、swiper
6、vue-echarts
7、vue-video-player
8、vue-photo-preview等等
6、vue-router 的模式有?
1、hash模式,用URL hash值來做路由,支持所有瀏覽器;該模式實現的路由,在通過鏈接後面
添加““#”+路由名字”。
2、history模式,由h5提供的history對象實現,依賴H5 History API和伺服器配置。
3、abstract模式,支持所有JS運行環境,如Node伺服器端,如果發現沒有瀏覽器的API,路由會
自動強制進入該模式。
7、組件之間如何傳值
Vue父子 組件之間傳值
子組件通過props來接受數據和通過$emit來觸發父組件的自定義事件
兄弟組件之間的傳值
建一個公共組件bus.js.。傳遞方通過事件觸發bus.$emit。接收方通過在mounted(){}生命周期
里觸發bus.$on。
可以通過VUEX 來跨組件傳參
父孫傳值 $attrs
(向下)$listeners
(向上)
祖先和子孫傳值provide/inject
獲取父組件實例this.$parent
8、路由之間如何傳參
- 通過router-link路由導航跳轉傳遞
<router-link to=`/a/${id}`>routerlink傳參</router-link>
- 跳轉時使用push方法拼接攜帶參數。
this.$router.push({
path: `/getlist/${id}`,
})
- 通過路由屬性中的name來確定匹配的路由,通過params來傳遞參數
this.$router.push({
name: 'Getlist',
params: {
id: id
}
})
- 使用path來匹配路由,然後通過query來傳遞參數。
this.$router.push({
path: '/getlist',
query: {
id: id
}
})
註意:query有點像ajax中的get請求,而params像post請求。
params在地址欄中不顯示參數,刷新頁面,參數丟失,
其餘方法在地址欄中顯示傳遞的參數,刷新頁面,參數不丟失。
9、VUEX
原理:Vuex是專門為vue.js應用程式設計的狀態管理工具。
1、state 保存vuex中的數據源,通過this.$store.state獲取
2、getters 用於監聽state中的值的變化,返回計算後的結果。getter的返回值會根據它的依賴
被緩存起來
3、mutations 是修改store中的值得唯一方式 //this.$store.commit('add')
4、action 官方建議提交一個actions,在actions中提交mutations再去修改狀態值。
this.$store.dispatch('add')
5、modules 模塊化
10、如何解決vuex頁面刷新數據丟失問題?
原因:因為vuex里的數據是保存在運行記憶體中的,當頁面刷新時,頁面會重新載入vue實例,vuex裡面的數據就會被清空。
解決方法:將vuex中的數據直接保存到瀏覽器緩存中。(一般是用sessionStorage)
11、computed和watch的區別?
computed值有緩存、觸發條件是依賴值發生更改、 watch無緩存支持非同步、監聽數據變化
computed: 是計算屬性,依賴其它屬性值,並且 computed 的值有緩存,只有它依賴的屬性值發生
改變,下一次獲取 computed 的值時才會重新計算 computed 的值;
watch: 更多的是觀察的作用,支持非同步,類似於某些數據的監聽回調 ,每當監聽的數據變化時都
會執行回調進行後續操作;
computed應用場景:需要進行數值計算,並且依賴於其它數據時,應該使用 computed,因為可以
利用 computed 的緩存特性,避免每次獲取值時,都要重新計算;
watch應用場景:需要在數據變化時執行非同步或開銷較大的操作時,應該使用 watch,使用 watch
選項允許我們執行非同步操作 ( 訪問一個 API ),限制我們執行該操作的頻率,併在我們得到最終結
果前,設置中間狀態。這些都是計算屬性無法做到的。
12、route和router的區別
- route:是路由信息對象,包括“path,parms,hash,name“等路由信息參數。
- router:是路由實例對象,包括了路由跳轉方法,鉤子函數等。
13、vue中數據變了但是視圖不跟新怎麼解決?
vue不能檢測以下變動的數組:
1、當你利用索引直接設置一個項時,vm.items[indexOfItem] = newValue
2、當你修改數組的長度時,例如: vm.items.length = newLength
對象屬性的添加或刪除
由於 Vue 會在初始化實例時對屬性執行 getter/setter 轉化過程,所以屬性必須在 data 對象上存在才能讓 Vue 轉換它,這樣才能讓它是響應的。
解決辦法:
使用 Vue.set(object, key, value) 方法將響應屬性添加到嵌套的對象上
Vue.set(vm.someObject, ‘b’, 2) 或者 this.$set(this.someObject,‘b’,2) (這也是全局 Vue.set 方法的別名)
非同步更新隊列
在最新的項目中遇到了這種情況,數據第一次獲取到了,也渲染了,但是第二次之後數據只有在再一次渲染頁面的時候更新,並不能實時更新。
Vue 非同步執行 DOM 更新。只要觀察到數據變化,Vue 將開啟一個隊列,並緩衝在同一事件迴圈中發生的所有數據改變。如果同一個 watcher 被多次觸發,只會被推入到隊列中一次。
解決辦法:
可在數據變化之後立即使用 Vue.nextTick(callback)。這樣回調函數在 DOM 更新完成後就會調用
14、vue中data為什麼是函數而不是對象?
vue組件是可復用的vue實例,一個組件被創建好之後,就可能被用在各個地方,而組件不管被覆用了多少次,組件中的data數據都應該是相互隔離,互不影響的.
基於這一理念,組件每復用一次,data數據就會被覆制一次,之後,當某一處復用的地方組件內data數據被改變時,其他復用地方組件的data數據不受影響。
如果data是對象的話,每當被覆用是,復用的對象和源對象都會指向同一個記憶體地址(淺拷貝),互相之間相互影響,所以要是函數
15、vue中父子組件傳值,父組件非同步請求,子組件不能實時更新怎麼解決?(vue中數據不能實時更新怎麼解決?)
首先瞭解父子組件生命周期執行順序
載入渲染數據過程
父組件 beforeCreate
父組件 created
父組件 beforeMount
子組件 beforeCreate
子組件 created
子組件 beforeMount
子組件 mounted
父組件 mounted
原因:因為生命周期只會執行一次,數據是要等到非同步請求以後才能拿到,那麼子組件的mounted鉤子執行的時候,還沒有拿到父組件傳遞過來的數據,但是又必須要列印出來結果,那這樣的話,就只能去列印props中的預設值空字元串了,所以列印的結果是一個空字元串。
解決辦法:
1、使用v-if控制組件渲染的時機
初始還沒拿到後端介面的非同步數據的時候,不讓組件渲染,等拿到的時候再去渲染組件。使用v-if="變數"去控制,初始讓這個變數為false,這樣的話,子組件就不會去渲染,等拿到數據的時候,再讓這個變數變成true,
舉例:
data() {
return {
isTrue:false // 初始為false
};
},
monted(){
this.$post.a.b.c.getData(res=>{
if(res.result){
this.isTrue = true
}
})
}
2、使用watch監聽數據的變化
舉例:
props: {
tableData: {
type: Array,
default: [],
},
},
watch: {
tableData(val){
console.log(val)
}
},
3、使用VueX
16、Vue 路由跳轉方式
router-link 標簽跳