1. 瀏覽器中,從輸入url到頁面顯示出來,具體的流程是什么?
1.DNS解析
2.TCP連接
3.發送HTTP請求
4.服務器處理請求並返回需要的數據
5.瀏覽器解析渲染頁面
解析HTML,生成DOM樹,解析CSS,生成CSSOM樹
將DOM樹和CSSOM樹結合,生成渲染樹(Render Tree)
Layout(回流):根據生成的渲染樹,進行回流(Layout),得到節點的幾何信息(位置,大小)
Painting(重繪):根據渲染樹以及回流得到的幾何信息,得到節點的絕對像素
Display:將像素發送給GPU,展示在頁面上
6.連接結束
2. http狀態碼的了解
1xx(臨時響應)
表示臨時響應並需要請求者繼續執行操作的狀態代碼
2xx (成功)
表示成功處理了請求的狀態碼。
常見的2開頭的狀態碼有:200 – 服務器成功返回網頁
3xx (重定向)
表示要完成請求,需要進一步操作。 通常,這些狀態代碼用來重定向
常見的3字開頭的狀態碼有:
301 (永久移動) 請求的網頁已永久移動到新位置。 服務器返回此響應時,會自動將請求者轉到新位置。
302 (臨時移動) 服務器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來進行以后的請求。
304 (未修改) 自從上次請求后,請求的網頁未修改過。 服務器返回此響應時,不會返回網頁內容。
4xx(請求錯誤) 這些狀態代碼表示請求可能出錯,妨礙了服務器的處理。
常見的4字開頭的狀態有:404 – 請求的網頁不存在
5xx(服務器錯誤)
這些狀態代碼表示服務器在嘗試處理請求時發生內部錯誤。 這些錯誤可能是服務器本身的錯誤,而不是請求出錯。
常見的以5開頭的狀態碼有:
500 (服務器內部錯誤) 服務器遇到錯誤,無法完成請求。
503 (服務不可用) 服務器目前無法使用(由於超載或停機維護)。 通常,這只是暫時狀態。
3. http2.0的優點?
解析速度快
服務器解析 HTTP1.1 的請求時,必須不斷地讀入字節,直到遇到分隔符 CRLF 為止。而解析 HTTP2 的請求就不用這么麻煩,因為 HTTP2 是基於幀的協議,每個幀都有表示幀長度的字段。
多路復用
HTTP1.1 如果要同時發起多個請求,就得建立多個 TCP 連接,因為一個 TCP 連接同時只能處理一個 HTTP1.1 的請求。
在 HTTP2 上,多個請求可以共用一個 TCP 連接,這稱為多路復用。同一個請求和響應用一個流來表示,並有唯一的流 ID 來標識。 多個請求和響應在 TCP 連接中可以亂序發送,到達目的地后再通過流 ID 重新組建。
首部壓縮
HTTP2 提供了首部壓縮功能。多請求請求時,有很多消息頭都是重復的。如果可以把相同的首部存儲起來,僅發送它們之間不同的部分,就可以節省不少的流量,加快請求的時間。
HTTP/2 在客戶端和服務器端使用“首部表”來跟蹤和存儲之前發送的鍵-值對,對於相同的數據,不再通過每次請求和響應發送。如果服務器收到了請求,它會照樣創建一張表。 當客戶端發送下一個請求的時候,如果首部相同,它可以直接發送這樣的首部塊:服務器會查找先前建立的表格,並把這些數字還原成索引對應的完整首部。
優先級
HTTP2 可以對比較緊急的請求設置一個較高的優先級,服務器在收到這樣的請求后,可以優先處理。
流量控制
由於一個 TCP 連接流量帶寬(根據客戶端到服務器的網絡帶寬而定)是固定的,當有多個請求並發時,一個請求占的流量多,另一個請求占的流量就會少。流量控制可以對不同的流的流量進行精確控制。
服務器推送
HTTP2 新增的一個強大的新功能,就是服務器可以對一個客戶端請求發送多個響應。換句話說,除了對最初請求的響應外,服務器還可以額外向客戶端推送資源,而無需客戶端明確地請求。
4. cookie,localStorage和sessionStorage的區別
cookie可以設置失效時間,但沒有自己的存取取的方法,需要時封裝,每次請求時跟隨請求發送,而localStorage和sessionStorage可以有自己存取的方法例如:setItem(),getItem(),removeItem(),clear() 如:localStorage.setItem(‘屬性’,值)
5. 設計模式知道那些?具體用法
單例模式:就是保證一個類只有一個實例,實現的方法一般是先判斷實例存在與否,如果存在直接返回,如果不存在就創建了再返回,這就確保了一個類只有一個實例對象。在JavaScript里,單例作為一個命名空間提供者,從全局命名空間里提供一個唯一的訪問點來訪問該對象。
觀察者模式: 觀察者的使用場合就是:當一個對象的改變需要同時改變其它對象,並且它不知道具體有多少對象需要改變的時候,就應該考慮使用觀察者模式。
工廠模式解決了重復實例化的問題,缺點,創建不同對象其中屬性和方法都會重復建立,消耗內存;還有函數識別問題等等。
6. 怎么處理web安全
可能的原因:
權限控制
SQL注入
URL安全測試
XSS(跨站腳本攻擊)
CSRF(跨站請求偽造)
URL跳轉漏洞
其他安全方面的考量
解決:1、永遠不要信任用戶的輸入。對用戶的輸入進行校驗,可以通過正則表達式或限制長度;對單引號和雙"-"進行轉換等。
2、永遠不要使用動態拼裝SQL,可以使用參數化的SQL或者直接使用存儲過程進行數據查詢存取。
3、永遠不要使用管理員權限的數據庫連接,為每個應用使用單獨的權限有限的數據庫連接。
4、不要把機密信息直接存放,加密或者Hash掉密碼和敏感的信息。
5、應用的異常信息應該給出盡可能少的提示,最好使用自定義的錯誤信息對原始錯誤信息進行包裝。
6、SQL注入的檢測方法一般采取輔助軟件或網站平台來檢測,軟件一般采用SQL注入檢測工具jsky、MDCSOFT SCAN等。采用MDCSOFT - IPS可以有效的防御SQL注入、XSS攻擊等。
使用https、HTTPS與HTTP雖然只差一個SSL,但是通信安全得到了大大的保障,通信的四大特性都以解決,解決方式如下:
機密性:混合算法
完整性:摘要算法
身份認證:數字簽名
不可否定:數字簽名
同時引入第三方證書機構,確保公開秘鑰的安全性
7. Seo是什么?怎么優化?
SEO(Search Engine Optimization):漢譯為搜索引擎優化。是一種方式:利用搜索引擎的規則提高網站在有關搜索引擎內的自然排名。目的是讓其在行業內占據領先地位,獲得品牌收益。很大程度上是網站經營者的一種商業行為,將自己或自己公司的排名前移。
優化:
SSR服務器渲染
靜態化
預渲染prerender-spa-plugin
使用Phantomjs針對爬蟲做處理
合理的title、description、keywords
語義化的HTML代碼,符合W3C規范
非裝飾性圖片必須加alt
友情鏈接
外鏈
向各大搜索引擎提交收錄自己的站點
重要的內容放在前面
少用iframe:iframe中的內容是不會被抓取到的
提高網站速度:這也是搜索引擎排序的一個重要指標
流量:訪問你的網站的人越多,排名也會越靠前.
8. 原生ajax的交互過程(即流程
先創建XHR對象即XMLHttpRequest()
然后open准備發送,open中有三個參數一是提交方式get和post,二是接口地址,三是同步和異步
第三步是用send發送
第四步再發送的過程中通過onreadystatechange來監聽接收的回調函數,可以通過判斷readyState==4和status==200來判斷是否成功返回,然后通過responseText接收成功返回的數據
9. 數組常用方法、用法是什么?
push,pop,unshift,shift,splice,join,concat,forEach,filter,map,sort,some,every
10. 數組排序
11. 數組去重
第一種:利用ES6的set來實現 例如:[...new Set(arr)]
第二種:借用臨時對象的方式
12. JS事件代理(也稱事件委托)是什么,及實現原理
JS事件代理就是通過給父級元素(例如:ul)綁定事件,不給子級元素(例如:li)綁定事件,然后當點擊子級元素時,通過事件冒泡機制在其綁定的父元素上觸發事件處理函數,主要目的是為了提升性能,因為我不用給每個子級元素綁定事件,只給父級元素綁定一次就好了,在原生js里面是通過event對象的targe屬性實現
var ul = document.querySelector("ul");
ul.onclick = function(e){//e指event,事件對象
var target = e.target || e.srcElement; //target獲取觸發事件的目標(li)
if(target.nodeName.toLowerCase() == 'li'){//目標(li)節點名轉小寫字母,不轉的話是大寫字母
alert(target.innerHTML)
}
}
jq方式實現相對而言簡單 $(“ul”).on(“click”,“li”,function(){//事件邏輯}) 其中第二個參數指的是觸發事件的具體目標,特別是給動態添加的元素綁定事件,這個特別起作用
13. 構造函數、原型、原型鏈、JS面試對象的理解
構造函數模式的目的就是為了創建一個自定義類,並且創建這個類的實例。構造函數模式中擁有了類和實例的概念,並且實例和實例之間是相互獨立的,即實例識別。
構造函數就是一個普通的函數,創建方式和普通函數沒有區別,不同的是構造函數習慣上首字母大寫。另外就是調用方式的不同,普通函數是直接調用,而構造函數需要使用new關鍵字來調用。
在JavaScript中,每當定義一個函數數據類型(普通函數、類)時候,都會天生自帶一個prototype屬性,這個屬性指向函數的原型對象,並且這個屬性是一個對象數據類型的值。
讓構造函數和實例原型之間的關系:
構造函數 + prototype = 實例原型
原型對象就相當於一個公共的區域,所有同一個類的實例都可以訪問到這個原型對象,我們可以將對象中共有的內容,統一設置到原型對象中。
在JavaScript中萬物都是對象,對象和對象之間也有關系,並不是孤立存在的。對象之間的繼承關系,在JavaScript中是通過prototype對象指向父類對象,直到指向Object對象為止,這樣就形成了一個原型指向的鏈條,專業術語稱之為原型鏈。
當我們訪問對象的一個屬性或方法時,它會先在對象自身中尋找,如果有則直接使用,如果沒有則會去原型對象中尋找,如果找到則直接使用。如果沒有則去原型的原型中尋找,直到找到Object對象的原型,Object對象的原型沒有原型,如果在Object原型中依然沒有找到,則返回undefined。
Object是JS中所有對象數據類型的基類(最頂層的類)在Object.prototype上沒有__proto__這個屬性。
面試對象:將所需要做的功能抽象成一個“對象”,然后反復調用這個對象來完成你想要的功能
14. 深拷貝、淺拷貝的區別,並實現深拷貝
對象淺拷貝可以理解為改變一個對象屬性值,另一個對象屬性也會發生改變,即互相影響,
對象深拷貝即就是說改變一個對象屬性,另一個對象屬性值不會發生改變,可以通過多種方法來實現對象深拷貝,
深拷貝方法:
第一種方法:通過JSON.stringify和JSON.parse來實現
var obj={name:’1610A’}
var obj2=JSON.parse(JSON.stringify(obj))
第二種方法:通過遞歸來實現
15. JS原生事件如何綁定
JS原生綁定事件主要為三種:
一是html事件處理程序
例如:<button onclick=”事件處理函數”>點我</button>
二是DOM0級事件處理程序
例如:var btn=document.getElementById(‘id元素’)
btn.onclick=function() {
//要處理的事件邏輯
}
三是DOM2級事件處理程序
例如: var btn=document.getElementById(‘id元素’)
//綁定事件
btn.addEventListener(‘click’,綁定的事件處理函數名,false)
//移除事件
btn.removeEventListener(‘click’,要移除的事件處理函數名,false)
16. ==與===的區別
== 用於比較兩者是否相等,忽略數據類型。
=== 用於更嚴謹的比較,值和值的數據類型都需要同時比較。
17. BFC相關?(div塌陷問題或者clearfix(清除浮動))
定位方式:普通流 (normal flow)、浮動 (float)、絕對定位 (absolute positioning)
BFC 即 Block Formatting Contexts (塊級格式化上下文):具有 BFC 特性的元素可以看作是隔離了的獨立容器,容器里面的元素不會在布局上影響到外面的元素,並且 BFC 具有普通容器所沒有的一些特性。
要元素滿足下面任一條件即可觸發 BFC 特性:
body 根元素
浮動元素:float 除 none 以外的值
絕對定位元素:position (absolute、fixed)
display 為 inline-block、table-cells、flex
overflow 除了 visible 以外的值 (hidden、auto、scroll)
BFC特性:
同一個 BFC 下外邊距會發生折疊
BFC 可以包含浮動的元素(清除浮動)
BFC 可以阻止元素被浮動元素覆蓋
清除浮動解決的方法有很多,主要目的是讓父級元素有高度
方法一:給父級元素設置絕對定位:position:absolute
方法二:給父級元素設置overflow:hidden;
方法三:通過偽對象來實現
.clearfix:after {
content: " ";
display: block;
clear: both;
height: 0;
}
18. 對盒模型的理解
盒模型其實就是瀏覽器把一個個標簽都看一個形象中的盒子,那每個盒子(即標簽)都會有內容(width,height),邊框(border),以及內容和邊框中間的縫隙(即內間距padding),還有盒子與盒子之間的外間距(即margin)
用圖表示為:
當然盒模型包括兩種:IE盒模型和w3c標准盒模型
IE盒模型總寬度即就是width寬度=border+padding+內容寬度
標准盒模型總寬度=border+padding+width
那如何在IE盒模型寬度和標准盒模型總寬度之間切換呢,可以通過box-sizing:border-box或設置成content-box來切換
其中:box-sizing:border-box //IE盒模型
box-sizing:content-box //w3c盒模型、
19. rem和em的區別?百分比與vw、vh的區別?
rem和em都是相對單位,主要參考的標簽不同:
rem是相對於根字號,即相對於<html>標簽的font-size實現的,瀏覽器默認字號是font-size:16px
em:是相對於父元素標簽的字號,和百分比%類似,%也是相對於父級的,只不過是%相對於父級寬度的,而em相對於父級字號的
百分比是相對於父元素標簽的寬度和高度
vw和vh分別相對於屏幕寬度和屏幕高度的,1vw相當於屏幕寬度的1%,100vw相當於滿屏寬度100%,
vh和vh類似,只不過是相對於屏幕高度的,1vh相當於屏幕高度的1%,100vh相當於滿屏高度的100%,
20. 塊元素和行內元素的區別
·塊級元素
總是從新的一行開始,即各個塊級元素獨占一行,默認垂直向下排列;
高度、寬度、margin及padding都是可控的,設置有效,有邊距效果;
寬度沒有設置時,默認為100%;
塊級元素中可以包含塊級元素和行內元素。
·行內元素
和其他元素都在一行,即行內元素和其他行內元素都會在一條水平線上排列;
高度、寬度是不可控的,設置無效,由內容決定。
根據標簽語義化的理念,行內元素最好只包含行內元素,不包含塊級元素。
21. 居中的方法有哪些?flex居中?
其實實現水平垂直劇中方法有很多:
定位:
第一種思路:通過給div設置絕對定位,並且left,right,top,bottom設置為0,margin:auto即可以水平垂直居中
通過給div設置絕對定位,left為50%,top為50%,再給div設置距左是自身的一半即:margin-left:自身寬度/2,margin-top:自身高度/2。
通過給div設置絕對定位,left為50%,top為50%,再給div設置跨左和跟上是自身的一半:transform:translate3d(-50%,-50%,0)
flex布局: display: flex; justify-content: center; align-items: center;
absolute + 負margin
absolute + margin auto
absolute + calc
absolute + transform
lineheight
writing-mode
table
css-table
grid
22. 重繪與回流
在HTML中,每個元素都可以理解成一個盒子,在瀏覽器解析過程中,會涉及到回流與重繪:
回流:布局引擎會根據各種樣式計算每個盒子在頁面上的大小與位置
重繪:當計算好盒模型的位置、大小及其他屬性后,瀏覽器根據每個盒子特性進行繪制
23. 怎么實現響應式布局
頁面元素寬度不用px作為單位,而是盡量使用百分比。
頁面框架之間使用流式布局,也就是用float屬性,這樣當元素超出屏幕寬度的時候會滑倒下面而不是撐出水平滾動條。
注意圖片的大小,尤其是寬度,同樣盡量使用百分比
使用CSS3中的Media Query(媒體查詢)針對不同寬度的設備設置不同的布局和樣式,從而適配不同的設備。
24. 防抖與節流
防抖和節流都是為了解決短時間內大量觸發某函數而導致的性能問題,比如觸發頻率過高導致的響應速度跟不上觸發頻率,出現延遲,假死或卡頓的現象
防抖:在事件被觸發n秒后再執行回調函數,如果在這n秒內又被觸發,則重新計時。
節流:規定一個單位時間,在這個單位時間內,只能有一次觸發事件的回調函數執行,如果在同一個單位時間內某事件被觸發多次,只有一次能生效。
防抖和節流的區別:
-- 效果:
函數防抖是某一段時間內只執行一次;而函數節流是間隔時間執行,不管事件觸發有多頻繁,都會保證在規定時間內一定會執行一次真正的事件處理函數。
-- 原理:
防抖是維護一個計時器,規定在delay時間后觸發函數,但是在delay時間內再次觸發的話,都會清除當前的 timer 然后重新設置超時調用,即重新計時。這樣一來,只有最后一次操作能被觸發。
節流是通過判斷是否到達一定時間來觸發函數,若沒到規定時間則使用計時器延后,而下一次事件則會重新設定計時器。
25. 什么是閉包?閉包的作用以及會導致什么問題
閉包說的通俗一點就是打通了一條在函數外部訪問函數內部作用域的通道。正常情況下函數外部是訪問不到函數內部作用域變量的,
表象判斷是不是閉包:函數嵌套函數,內部函數被return 內部函數調用外層函數的局部變量
優點:可以隔離作用域,不造成全局污染
缺點:由於閉包長期駐留內存,則長期這樣會導致內存泄露
如何解決內存泄露:將暴露全外部的閉包變量置為null
適用場景:封裝組件,for循環和定時器結合使用,for循環和dom事件結合.可以在性能優化的過程中,節流防抖函數的使用,導航欄獲取下標的使用
26. 什么是跨域,怎么解決?
基於ajax同源策略,因為安全的考慮,ajax不允許訪問不同域名下的資源
只存在前后端訪問,后端訪問后端不存在跨域問題。
產生跨域的情況有:不同協議,不同域名,不同端口以及域名和ip地址的訪問都會產生跨域。
解決:
一、是jsonp
jsonp實現原理:主要是利用動態創建script標簽請求后端接口地址,然后傳遞callback參數,后端接收callback,后端經過數據處理,返回callback函數調用的形式,callback中的參數就是json
二、 是代理(前端代理和后端代理)
前端代理我在vue中主要是通過vue腳手架中的config中的index文件來配置的,其中有個proxyTable來配置跨域的
三、是CORS
CORS全稱叫跨域資源共享,主要是后台工程師設置后端代碼來達到前端跨域請求的
27. vuex的模塊、流程、異步時action?vuex數據持久化?
vuex是一個狀態管理工具,主要解決大中型復雜項目的數據共享問題,主要包括state,actions,mutations,getters和modules 5個要素,
主要流程:組件通過dispatch到 actions,actions是異步操作,再actions中通過commit到mutations,mutations再通過邏輯操作改變state,從而同步到組件,更新其數據狀態
getters相當於組件的計算屬性對,組件中獲取到的數據做提前處理的.再說到輔助函數的作用.
因為vuex中的state是存儲在內存中的,一刷新就沒了,例如登錄狀態,常見解決方案有:
第一種:利用H5的本地存儲(localStorage,sessionStorage)
第二種:利用第三方封裝好的插件,例如:vuex-persistedstate
第三種:使用vue-cookie插件來做存儲
28. 同步和異步的理解?異步解決方案?回調地獄? Promise?async/await?自己實現promise?
同步即sync,形象的說就是代碼一行行執行,前面代碼和請求沒有執行完,后面的代碼和請求就不會被執行
異步:即async,形象的說就是代碼可以在當前程序沒有執行完,也可以執行后面的代碼
異步解決方案主要有:
l 回調函數
l promise
l generator
l async和await
回調地獄:為了實現某些邏輯經常會寫出層層嵌套的回調函數,如果嵌套過多,會極大影響代碼可讀性和邏輯,這種情況也被成為回調地獄
promise的狀態改變一次以后就不會再改變,鏈式調用:then返回的是一個Promise對象,所以能進行鏈式調用。
async/await其實是Promise的語法糖, async 會將其后的函數(函數表達式或 Lambda)的返回值封裝成一個 Promise 對象,而 await 會等待這個 Promise 完成,並將其 resolve 的結果返回出來。
async function doIt() {
console.time('doIt');
let time1 = 300;
let time2 = await step1(time1);//將Promise對象resolve(n+200)的值賦給time2
let time3 = await step1(time2);
let result = await step1(time3);
console.log(`result is ${result}`);
console.timeEnd('doIt');
}
29. 性能優化?
方面:
加載優化
渲染優化
內存優化
電源優化
核心:減少前端資源數量,減小前端資源大小,減少dom操作
代碼層面:注意事件的銷毀、路由懶加載、提取公共代碼、css放前面、組件懶加載、減少代碼體積大小、字體圖標代替圖片、使用事件委托、使用查找表、不覆蓋原生方法、減低css選擇器復雜度、使用flex、使用 transform 和 opacity實現動畫
交互優化:減少請求數量、使用 HTTP2(頭部壓縮、鏈路復用、解析快、可設置優先級、流量控制、服務器推送)、減少重繪重排(innerHTML代替DOM操作、避免使用動態屬性、脫離文檔流操作再合並)
加載優化:按需引入、使用CDN、使用服務端渲染、善用緩存、避免卡頓
打包優化:使用gzip、Webpack 對圖片進行壓縮、webpack 按需加載代碼、提取第三庫代碼、webpack物理打包以及配置項打包優化
其他優化:圖片優化(壓縮、懶加載、用webp格式,延遲加載、響應式圖片)、使用工作線程Web Workers、少用全局變量
我寫過一篇文檔:https://www.cnblogs.com/clwydjgs/p/14741264.html
30. es6新特性
ES6新增特性常用的主要有:let/const,箭頭函數,模板字符串,解構賦值,模塊的導入(import)和導出(export default/export),Promise,還有一些數組字符串的新方法,其實有很多,我平時常用的就這些
31. 說一下call,apply,bind區別
call,apply,bind主要作用都是改變this指向的,但使用上略有區別,說一下區別:
call和apply的主要區別是在傳遞參數上不同,call后面傳遞的參數是以逗號的形式分開的,apply傳遞的參數是數組形式、Apply是以A開頭的,所以應該是跟Array(數組)形式的參數]
bind返回的是一個函數形式,如果要執行,則后面要再加一個小括號 例如:bind(obj,參數1,參數2,)(),bind只能以逗號分隔形式,不能是數組形式
32. var let const
var的問題:存在變量提升,后面聲明的變量會覆蓋前面的變量聲明、作用域不可控。
33. 單項數據流、雙向數據流
Vue是單項數據流,數據雙向綁定
單向數據流主要是vue 組件間傳遞數據是單向的,即數據總是由父組件傳遞給子組件,子組件在其內部維護自己的數據,但它無權修改父組件傳遞給它的數據,當開發者嘗試這樣做的時候,vue 將會報錯。
34. SPA和MPA?
單頁應用SPA是一種網絡應用程序或網站的模型,它通過動態重寫當前頁面來與用戶交互,這種方法避免了頁面之間切換打斷用戶體驗在單頁應用中,所有必要的代碼(HTML、JavaScript和CSS)都通過單個頁面的加載而檢索
多頁應用MPA(MultiPage-page application),翻譯過來就是多頁應用在MPA中,每個頁面都是一個主頁面,都是獨立的當我們在訪問另一個頁面的時候,都需要重新加載html、css、js文件
我們熟知的JS框架如react,vue,angular,ember都屬於SPA
單頁應用與多頁應用的區別
|
單頁面應用(SPA) |
多頁面應用(MPA) |
組成 |
一個主頁面和多個頁面片段 |
多個主頁面 |
刷新方式 |
局部刷新 |
整頁刷新 |
url模式 |
哈希模式 |
歷史模式 |
SEO搜索引擎優化 |
難實現,可使用SSR方式改善 |
容易實現 |
數據傳遞 |
容易 |
通過url、cookie、localStorage等傳遞 |
頁面切換 |
速度快,用戶體驗良好 |
切換加載資源,速度慢,用戶體驗差 |
維護成本 |
相對容易 |
相對復雜 |
單頁應用優缺點
優點:
具有桌面應用的即時性、網站的可移植性和可訪問性
用戶體驗好、快,內容的改變不需要重新加載整個頁面
良好的前后端分離,分工更明確
缺點:
不利於搜索引擎的抓取
首次渲染速度相對較慢
35. mvc與mvvm
MVVM 由 Model,View,ViewModel 三部分構成,Model 層代表數據模型,也可以在Model中定義數據修改和操作的業務邏輯;View 代表UI 組件,它負責將數據模型轉化成UI 展現出來,ViewModel 是一個同步View 和 Model的對象。
在MVVM架構下,View 和 Model 之間並沒有直接的聯系,而是通過ViewModel進行交互,Model 和 ViewModel 之間的交互是雙向的, 因此View 數據的變化會同步到Model中,而Model 數據的變化也會立即反應到View 上。
ViewModel 通過雙向數據綁定把 View 層和 Model 層連接了起來,而View 和 Model 之間的同步工作完全是自動的,無需人為干涉,因此開發者只需關注業務邏輯,不需要手動操作DOM, 不需要關注數據狀態的同步問題,復雜的數據狀態維護完全由 MVVM 來統一管理。
36. vue中,data為什么是函數?
作用域問題,為了保證互不干擾,因為一個組件是可以共享的,但他們的data是私有的,所以每個組件都要return一個新的data對象,返回一個唯一的對象,不要和其他組件共用一個對象。而且data也是一個閉包的經典使用常見。
37. this關鍵字
this指向直接調用者,而非間接調用者
普通函數中的this:
在Vue所有的生命周期鈎子方法(如created,mounted, updated以及destroyed)里 使用this,this指向調用它的Vue實例,即(new Vue)。
箭頭函數中的this
箭頭函數沒有自己的this, 它的this是繼承而來; 默認指向在定義它時所處的對象(宿主對象),而不是執行時的對象, 定義它的時候,可能環境是window; 箭頭函數可以方便地讓我們在 setTimeout ,setInterval中方便的使用this
38. Vue生命周期
vue生命周期即為一個組件從出生到死亡的一個完整周期,主要包括以下4個階段:創建,掛載,更新,銷毀
創建前:beforeCreate, 創建后:created(有data,無$el)
掛載前:beforeMount, 掛載后:mounted(有data,有$el)
更新前:beforeUpdate, 更新后:updated
銷毀前:beforeDestroy, 銷毀后:destroyed
新增了使用內置組件 keep-alive 來緩存實例,而不是頻繁創建和銷毀(開銷大)
actived 實例激活(該鈎子在服務器端渲染期間不被調用。)
deactived 實例失效 (該鈎子在服務器端渲染期間不被調用。)
39. Vue-router路由?路由守衛?懶加載?replace和push的區別?
前端路由實現原理主要通過以下兩種技術實現的
第一種:利用H5的history API實現
主要通過history.pushState 和 history.replaceState來實現,不同之處在於,pushState會增加一條新的歷史記錄,而replaceState則會替換當前的歷史記錄[發布項目時,需要配置下apache]
第二種:利用url的hash實現
我們經常在 url 中看到 #,這個 # 有兩種情況,一個是我們所謂的錨點,路由里的 # 不叫錨點,我們稱之為 hash,我們說的就是hash,主要利用監聽哈希值的變化來觸發事件 —— hashchange 事件來做頁面局部更新
第三種:abstract模式
適用於所有JavaScript環境,例如服務器端使用Node.js。如果沒有瀏覽器API,路由器將自動被強制進入此模式。
總結:hash 方案兼容性好,而H5的history主要針對高級瀏覽器。
路由守衛:
第一種:全局路由鈎子 beforeEach(to,from,next) { }
第二種:路由獨享的鈎子
beforeEnter(to,from,next) {
}
第三種:組件內的鈎子
beforeRouteEnter(to,from,next) {
//…
}
beforeRouteUpdate(to,from,next) {
//…
}
beforeRouteLeave(to,from,next) {
//…
}
適用場景:動態設置頁面標題,判斷用戶登錄權限等
vue路由懶加載主要解決打包后文件過大的問題,事件觸發才加載對應組件中的js
this.$router.replace方法方法,不計入history記錄,this.$router. Push計入歷史
40. 雙向綁定的原理,手寫
利用ES5中的Object.defineProperty結合觀察者模式實現的,然后利用里面的getter和setter來實現雙向數據綁定的、發布訂閱模式,數據劫持
首先要對數據進行劫持監聽,設置一個監聽器Observer,用來監聽所有屬性。如果屬性發上變化了,就需要告訴訂閱者Watcher看是否需要更新。因為訂閱者是有很多個,所以我們需要有一個消息訂閱器Dep來專門收集這些訂閱者,然后在監聽器Observer和訂閱者Watcher之間進行統一管理的。接着,我們還需要有一個指令解析器Compile,對每個節點元素進行掃描和解析,將相關指令(如v-model,v-on)對應初始化成一個訂閱者Watcher,並替換模板數據或者綁定相應的函數,此時當訂閱者Watcher接收到相應屬性的變化,就會執行對應的更新函數,從而更新視圖。
41. packJson.js詳細配置?
42. Vue異步隊列?nextTick是什么?適用場景?
異步更新隊列:Vue在觀察到數據變化時並不是直接更新DOM,而是開啟一個隊列,並緩沖在同一個事件循環中發生的所以數據改變。在緩沖時會去除重復數據,從而避免不必要的計算和DOM操作。然后,在下一個事件循環tick中,Vue刷新隊列並執行實際(已去重的)工作。
因為Vue的異步更新隊列,$nextTick是用來知道什么時候DOM更新完成的
vue中的nextTick主要用於處理數據動態變化后,DOM還未及時更新的問題,用nextTick就可以獲取數據更新后最新DOM的變化
適用場景:
第一種:有時需要根據數據動態的為頁面某些dom元素添加事件,這就要求在dom元素渲染完畢時去設置,但是created與mounted函數執行時一般dom並沒有渲染完畢,所以就會出現獲取不到,添加不了事件的問題,這回就要用到nextTick處理
第二種:在使用某個第三方插件時 ,希望在vue生成的某些dom動態發生變化時重新應用該插件,也會用到該方法,這時候就需要在 $nextTick 的回調函數中執行重新應用插件的方法,例如:應用滾動插件better-scroll時
第三種:數據改變后獲取焦點
43. vue核心是什么? vue和jquey的區別?vue與React
vue最大特點我感覺就是“組件化“和”數據驅動“
組件化就是可以將頁面和頁面中可復用的元素都看做成組件,寫頁面的過程,就是寫組件,然后頁面是由這些組件“拼接“起來的組件樹
數據驅動就是讓我們只關注數據層,只要數據變化,頁面(即視圖層)會自動更新,至於如何操作dom,完全交由vue去完成,咱們只關注數據,數據變了,頁面自動同步變化了,很方便
jquery主要是玩dom操作的“神器“,強大的選擇器,封裝了好多好用的dom操作方法和如何獲取ajax方法 例如:$.ajax()非常好用
vue:主要用於數據驅動和組件化,很少操作dom,當然vue可能通過ref來選擇一個dom或組件
vue與react:
相同點:數據驅動視圖、組件化、都使用 Virtual DOM
不同點:核心思想不同、組件寫法差異、diff算法不同、響應式原理不同
44. vue3.新特性0,ts?
特性:引入Tree-shaking,多出setup生命周期、響應式API、響應式偵聽、Composition API(組合API)、Fragment、Teleport、Suspense等
45. Vue常用的修飾符
v-on 指令常用修飾符:
.stop - 調用 event.stopPropagation(),禁止事件冒泡。
.prevent - 調用 event.preventDefault(),阻止事件默認行為。
.capture - 添加事件偵聽器時使用 capture 模式。
.self - 只當事件是從偵聽器綁定的元素本身觸發時才觸發回調。
.{keyCode | keyAlias} - 只當事件是從特定鍵觸發時才觸發回調。
.native - 監聽組件根元素的原生事件。
.once - 只觸發一次回調。
.left - (2.2.0) 只當點擊鼠標左鍵時觸發。
.right - (2.2.0) 只當點擊鼠標右鍵時觸發。
.middle - (2.2.0) 只當點擊鼠標中鍵時觸發。
.passive - (2.3.0) 以 { passive: true } 模式添加偵聽器
注意: 如果是在自己封裝的組件或者是使用一些第三方的UI庫時,會發現並不起效果,這時就需要用`·.native修飾符了,如:
//使用示例:
<el-input
v-model="inputName"
placeholder="搜索你的文件"
@keyup.enter.native="searchFile(params)"
>
</el-input>
v-bind 指令常用修飾符:
.prop - 被用於綁定 DOM 屬性 (property)。(差別在哪里?)
.camel - (2.1.0+) 將 kebab-case 特性名轉換為 camelCase. (從 2.1.0 開始支持)
.sync (2.3.0+) 語法糖,會擴展成一個更新父組件綁定值的 v-on 偵聽器。
v-model 指令常用修飾符:
.lazy - 取代 input 監聽 change 事件
.number - 輸入字符串轉為數字
.trim - 輸入首尾空格過濾
46. v-for與v-show的區? v-for與v-if優先級
v-if和v-show都可以顯示和隱藏一個元素,但有本質區別
v-if是惰性的,只是值為false就不會加載對應元素,為true才動態加載對應元素
v-show:是無論為true和為false都會加載對應html代碼,但為false時用display:none隱藏不在頁面顯示,但為true時頁面上用display:block顯示其效果
適用場景:切換頻繁的場合用v-show,切換不頻繁的場合用v-if
v-for的優先級比v-if更高,這意味着 v-if將分別重復運行於每個 v-for循環中。當你想為僅有的一些項渲染節點時,這種優先級的機制會十分有用
47. 虛擬dom是什么,有什么用
提前使用js的方式表示出dom結構樹來.存儲在內存里面.同樣的循環.只會最終合並執行一次,大大的提高了性能.(這個地方有點兒像js中的createElementFragment文檔碎片)
而在對比的過程中.通過diff算法進行比較差異.這個比較在我理解而言就是同層比較.降低了時間復雜度空間復雜度一些什么玩意兒.最終把差異同步到真實dom上去.這就是我理解的虛擬dom
在傳統的jq中,操作的都是真實的DOM,.而一個真實dom的渲染過程,要經過渲染引擎構建DOM樹.構建樣式表.組建成render(渲染)樹,的過程,要經過不斷的重繪回流才能夠展示給用戶.
那么在直接js操作dom的過程中,比方說一個循環10次插入dom元素,其實每一次都會經歷上面的過程..經歷大量的重繪回流.代價特別大.性能低下.所以出現了虛擬dom
48. diff算法
diff 算法是一種通過同層的樹節點進行比較的高效算法
其有兩個特點:
比較只會在同層級進行, 不會跨層級比較
在diff比較的過程中,循環從兩邊向中間比較
diff 算法在很多場景下都有應用,在 vue 中,作用於虛擬 dom 渲染成真實 dom 的新舊 VNode 節點比較
原理:當數據發生改變時,set方法會調用Dep.notify通知所有訂閱者Watcher,訂閱者就會調用patch給真實的DOM打補丁,更新相應的視圖
源碼位置:src/core/vdom/patch.js
49. 解構賦值
一種 Javascript 表達式。通過解構賦值, 可以將屬性/值從對象/數組中取出,賦值給其他變量。
一維:深拷貝
二位:淺拷貝
50. vue過濾器做什么的(vue1.x和vue2.x這塊的區別)
vue過濾器主要用於對渲染出來的數據進行格式化處理。例如:后台返回的數據性別用0和1表示,但渲染到頁面上不能是0和1我得轉換為“男“和”女”,這時就會用到過濾器,還有商品價格讀取出來的是普通數值,例如:230035,但我要在前面加個貨幣符號和千分分隔等,例如變成:¥230,035,都得需要vue過濾器
創建過濾器,跟創建自定義指令類似,也有全局和局部過濾器的形式
全局過濾器:Vue.filter(‘過濾器名’,function(參數1,參數2,…) {
//………..
return 要返回的數據格式
})
局部過濾器:在組件內部添加filters屬性來定義過濾器
fitlers:{
過濾器名(參數1,參數2,,…參數n) {
//………..
return 要返回的數據格式
}
}
51. vue組件通訊(即傳值)?
第一種:父傳子:主要通過props來實現的
具體實現:父組件通過import引入子組件,並注冊,在子組件標簽上添加要傳遞的屬性,子組件通過props接收,接收有兩種形式一是通過數組形式[‘要接收的屬性’ ],二是通過對象形式{ }來接收,對象形式可以設置要傳遞的數據類型和默認值,而數組只是簡單的接收
第二種:子傳父:主要通過$emit來實現
具體實現:子組件通過通過綁定事件觸發函數,在其中設置this.$emit(‘要派發的自定義事件’,要傳遞的值),$emit中有兩個參數一是要派發的自定義事件,第二個參數是要傳遞的值
然后父組件中,在這個子組件身上@派發的自定義事件,綁定事件觸發的methods中的方法接受的默認值,就是傳遞過來的參數
第三種:兄弟之間傳值有兩種方法:
方法一:通過event bus實現
具體實現:創建一個空的vue並暴露出去,這個作為公共的bus,即當作兩個組件的橋梁,在兩個兄弟組件中分別引入剛才創建的bus,在組件A中通過bus.$emit(’自定義事件名’,要發送的值)發送數據,在組件B中通過bus.$on(‘自定義事件名‘,function(v) { //v即為要接收的值 })接收數據
方法二:通過vuex實現
具體實現:vuex是一個狀態管理工具,主要解決大中型復雜項目的數據共享問題,主要包括state,actions,mutations,getters和modules 5個要素,主要流程:組件通過dispatch到 actions,actions是異步操作,再actions中通過commit到mutations,mutations再通過邏輯操作改變state,從而同步到組件,更新其數據狀態
方法三:使用全局的變量傳遞
在windons或document上聲明或綁定數據,取值
52. vue中methods,computed,watch的區別?
computed是多對一的關系,而watch則是一對多的關系;
methods中都是封裝好的函數,無論是否有變化只要觸發就會執行
computed:是vue獨有的特性計算屬性,可以對data中的依賴項再重新計算,得到一個新值,應用到視圖中,和methods本質區別是computed是可緩存的,也就是說computed中的依賴項沒有變化,則computed中的值就不會重新計算,而methods中的函數是沒有緩存的。Watch是監聽data和計算屬性中的新舊變化。
53. Vue中,怎么設置局部樣式?原理?樣式穿透?
css沒有局部樣式的概念,vue腳手架通過實現了,即在style標簽上添加scoped,
scoped的實現原理:vue通過postcss給每個dom元素添加一個以data-開頭的隨機自定義屬性、然后css根據屬性選擇器添加樣式
第三方庫的樣式穿透:
less/sass穿透問題 >>> /deep/
聲明全局樣式,樣式加后加 !important
將樣式impoimport至App的上方
54. vue中 keep-alive 組件的作用
keep-alive:主要用於保留組件狀態或避免重新渲染。
比如: 有一個列表頁面和一個 詳情頁面,那么用戶就會經常執行打開詳情=>返回列表=>打開詳情這樣的話 列表 和 詳情 都是一個頻率很高的頁面,那么就可以對列表組件使用<keep-alive></keep-alive>進行緩存,這樣用戶每次返回列表的時候,都能從緩存中快速渲染,而不是重新渲染。
1、屬性:
include:字符串或正則表達式。只有匹配的組件會被緩存。
exclude:字符串或正則表達式。任何匹配的組件都不會被緩存。
2、用法:
包裹動態組件時,會緩存不活動的組件實例,而不是銷毀它們。和 <transition>相似,<keep-alive>是一個抽象組件:它自身不會渲染一DOM 元素,也不會出現在父組件鏈中。
當組件在<keep-alive> 內被切換,在 2.2.0 及其更高版本中,activated 和 deactivated生命周期 將會在 樹內的所有嵌套組件中觸發。
55. vue中,props與data優先級
props > methods>data>computed>watch
56. webpack了解多少?
webpack是一個前端模塊化打包構建工具,vue腳手架本身就用的webpack來構建的,webpack本身需要的入口文件通過entry來指定,出口通過output來指定,默認只支持js文件,其他文件類型需要通過對應的loader來轉換,例如:less需要less,less-loader,sass需要sass-loader,css需要style-loader,css-loader來實現。當然本身還有一些內置的插件來對文件進行壓縮合並等操作
插件:性能分析webpack-bundle-analyzer
你遇到過什么大的難題,怎么解決
職業規划