HTML、CSS相關
HTML5新特性
input新增了一些屬性:color-調色板、tel-電話、number-數字、date-年月日
video、aideo視音頻標簽
語義化標簽
語義化
語義化標簽 : header、nav、main、footer
語義化的優點有:
(一)代碼結構清晰,易於閱讀,利於開發和維護
(二)方便設備解析根據語義渲染網頁
(三)有利於(SEO)搜索引擎優化
(四)在瀏覽器css失效時,頁面依然可讀
如何語義化:不用純樣式標簽(b、i、u)、少用無語義標簽(div、span)、使用語義化標簽
盒模型
所有HTML元素都可以看做是一個作盒子,在CSS中,"box model"這一術語是用來設計和布局時使用。
W3C盒子模型(標准盒子模型):寬=內部寬度(content)+border+padding+margin
IE盒子模型(怪異盒子模型):寬=內部寬度(content+border+padding)+margin
互換模型格式:
box-sizing:content-box;//變為標准盒模型(大部分瀏覽器默認)
box-sizing:border-box;//變為怪異盒子模型
行內元素、塊級元素、空元素有哪些?區別?
1、行內元素:span、a、em、img、input
2、塊級元素:div、ol、ul、form
3、空元素:br、hr、img、input
區別:
行內元素不換行、塊級元素換行
正常情況下是塊級元素包含行內元素,鮮少有行內元素包含塊級元素
沒有內容的標簽稱之為空元素,空元素是在開始標簽中關閉的。
離線緩存與傳統瀏覽器緩存的區別
離線緩存是整個應用,傳統瀏覽器緩存是單個文件
離線緩存斷網后依然可以打開頁面,傳統瀏覽器緩存不可以
離線緩斷在有網絡情況下優先使用緩存,傳統瀏覽器緩存會通知網絡更新緩存
能不能說一說瀏覽器的本地存儲?各自優劣如何?
瀏覽器的本地存儲主要分為Cookie、WebStorage, 其中WebStorage又可以分為localStorage和sessionStorage。
共同點: 都會在瀏覽器端保存,有大小和同源限制
不同點:
一、cookie數據始終在同源的http請求中攜帶,即cookie在瀏覽器和服務器間來回傳遞。sessionStorage和localStorage不會自動把數據發送給服務器,僅在本地保存。
二、存儲大小限制也不同:cookie數據不能超過4K,sessionStorage和localStorage可以達到5M或者更多
三、作用域不同:sessionStorage:僅在當前瀏覽器窗口關閉之前有效;localstorage:數據始終有效,窗口或瀏覽器關閉也一直保存,除非刪除數據;cookie:在設置的cookie過期時間之前有效,即使窗口關閉或瀏覽器關閉
CSS樣式優先級
!important>style>id>class
BFC
BFC 即塊格式化上下文。BFC內的元素不會影響外面的元素。
創建:
1.float不為none
2.position為absolute或fixed
3.overflow不為visible
4.display為inline-block、flex、inline-flex等
應用:
1. 防止margin重疊
2. 清除內部浮動
3. 自適應多欄布局
三欄布局
絕對定位法:中間欄目使用margin/padding空出左右位置,左右使用絕對定位
浮動法:中間欄目使用margin/padding空出左右位置,左右使用浮動定位
Flex:flex:1
Grid:父元素:display:grid 子元素:grid-template-columns:100px auto 20px
CSS選擇器
標簽選擇器
ID選擇器
類選擇器
組選擇器
通配符選擇器
后代選擇器
子元素選擇器
偽類選擇器
Flex:1是什么
經常用於自適應布局。也就是flex-grow、flex-shrink、flex-basis的縮寫
Display:flex的常用屬性
flex-drection:設置主軸方向
Justify-content:設置主軸排列方式
Flex-wrap:設置是否換行
Align-content/align-item:側軸排列(多行/單行)
預處理器less、sass
是css中一種抽象層。好處:
1.結構清晰、便於擴展
2.方便屏蔽瀏覽器的語法差異
3.多重繼承
DOM、BOM對象
BOM是指瀏覽器對象模型,可以對瀏覽器窗口進行訪問和操作。使用 BOM,開發者可以移動窗口、改變狀態欄中的文本以及執行其他與頁面內容不直接相關的動作。
DOM 是指文檔對象模型,通過它,可以訪問HTML文檔的所有元素。 DOM 是 W3C的標准。
瀏覽器渲染機制
網頁生成過程:
1.HTML被HTML解析器解析成DOM 樹
2.css則被css解析器解析成CSSOM 樹
3.結合DOM樹和CSSOM樹,生成一棵渲染樹(Render Tree)
4.生成布局(flow),即將所有渲染樹的所有節點進行平面合成
5.將布局繪制(paint)在屏幕上
重排(也稱回流)
當DOM的變化影響了元素的幾何信息(DOM對象的位置和尺寸大小),瀏覽器需要重新計算元素的幾何屬性,將其安放在界面中的正確位置,這個過程叫做重排。 觸發:添加或者刪除可見的DOM元素、元素尺寸改變——邊距、填充、邊框、寬度和高度
重繪
當一個元素的外觀發生改變,但沒有改變布局,重新把元素外觀繪制出來的過程,叫做重繪。 觸發:改變元素的color、background、box-shadow等屬性
重排重繪優化建議
1.樣式表越簡單,重排和重繪就越快。盡量用class,少用style一條條改變樣式
2.重排和重繪的DOM元素層級越高,成本就越高。如果可以靈活用display,absolute,flex等重排開銷會比較小,或不會影響其他元素的重排。
3.使用虛擬DOM的腳本庫。
JS相關
js數據類型、typeof、instanceof
1) string、number、boolean、null、undefined、object(function、array)、symbol
2) typeof 主要用來判斷數據類型
3) instanceof 判斷該對象是誰的實例。
ES6
1. 新增symbol類型 表示獨一無二的值,用來定義獨一無二的對象屬性名;
2. const/let 都是用來聲明變量,不可重復聲明,具有塊級作用域。存在暫時性死區,也就是不存在變量提升。(const一般用於聲明常量);
3. 變量的解構賦值(包含數組、對象、字符串、數字及布爾值,函數參數),剩余運算符(...rest);
4. 模板字符串(${data});
5. 擴展運算符(數組、對象);;
6. 箭頭函數;
7. Set和Map數據結構;
8. Proxy/Reflect;
9. Promise
ES6里的symble
它的功能類似於一種標識唯一性的ID,每個Symbol實例都是唯一的。 Symbol類型的key是不能通過Object.keys()或者for...in來枚舉的, 它未被包含在對象自身的屬性名集合(property names)之中。 所以,利用該特性,我們可以把一些不需要對外操作和訪問的屬性使用Symbol來定義。
ES6里的set和map
- Map對象保存鍵值對。任何值(對象或者原始值) 都可以作為一個鍵或一個值。構造函數Map可以接受一個數組作為參數。
- Set對象允許你存儲任何類型的值,無論是原始值或者是對象引用。它類似於數組,但是成員的值都是唯一的,沒有重復的值。
vue的key
1.key的作用主要是為了高效的更新虛擬DOM,其原理是vue在patch過程中通過key可以精准判斷兩個節點是否是同一個,從而避免頻繁更新不同元素,使得整個patch過程更加高效,減少DOM操作量,提高性能。
2.另外,若不設置key還可能在列表更新時引發一些隱蔽的bug
3. vue中在使用相同標簽名元素的過渡切換時,也會使用到key屬性,其目的也是為了讓vue可以區分它們, 否則vue只會替換其內部屬性而不會觸發過渡效果。
普通函數和箭頭函數的區別
1.箭頭函數是匿名函數,不能作為構造函數,不能使用new
2.箭頭函數不綁定arguments,取而代之用rest參數...解決
3.箭頭函數不綁定this,會捕獲其所在的上下文的this值,作為自己的this值
4.箭頭函數通過 call() 或 apply() 方法調用一個函數時,只傳入了一個參數,對 this 並沒有影響。
5.箭頭函數不能當做Generator函數,不能使用yield關鍵字
閉包(高頻)
閉包是指有權訪問另一個函數作用域中的變量的函數 當函數可以記住並訪問所在的詞法作用域時,就產生了閉包,即使函數是在當前詞法作用域之外執行
- 閉包用途:
能夠訪問函數定義時所在的詞法作用域(阻止其被回收)
私有化變量
模擬塊級作用域
創建模塊
- 閉包缺點:會導致函數的變量一直保存在內存中,過多的閉包可能會導致內存泄漏
原型、原型鏈(高頻)
原型: 對象中固有的__proto__屬性,該屬性指向對象的prototype原型屬性。
原型鏈: 當我們訪問一個對象的屬性時,如果這個對象內部不存在這個屬性,那么它就會去它的原型對象里找這個屬性,這個原型對象又會有自己的原型,於是就這樣一直找下去,也就是原型鏈的概念。原型鏈的盡頭一般來說都是Object.prototype所以這就是我們新建的對象為什么能夠使用toString()等方法的原因。
特點: JavaScript對象是通過引用來傳遞的,我們創建的每個新對象實體中並沒有一份屬於自己的原型副本。當我們修改原型時,與之相關的對象也會繼承這一改變。
this指向
代表的是當前上下文環境對象。在面向對象語言中this表示當前對象的一個引用。但在JavaScript中this是不固定的,它會隨着環境的改變而改變。
1) 在方法中,this表示該方法所屬的對象
2) 在單獨使用的情況下,this代表的是全局對象
3) 在函數中,this表示的是全局對象
4) 在函數中但是在嚴格模式下,this為未定義(undefined)
5) 在事件中,this表示的是接收事件的元素
類似call、apply等方法可以改變this引用到的對象apply 、 call 和 bind 調用模式,這三個方法都可以顯示的指定調用函數的 this 指向。apply接收參數的是數組,call接受參數列表,bind方法傳入一個對象。
new關鍵字
1.首先創建了一個新的空對象
2.設置原型,將對象的原型設置為函數的prototype對象。
3.讓函數的this指向這個對象,執行構造函數的代碼(為這個新對象添加屬性)
4.判斷函數的返回值類型,如果是值類型,返回創建的對象。如果是引用類型,就返回這個引用類型的對象。
作用域、作用域鏈
作用域負責收集和維護由所有聲明的標識符(變量)組成的一系列查詢,並實施一套非常嚴格的規則,確定當前執行的代碼對這些標識符的訪問權限。(全局作用域、函數作用域、塊級作用域)。 作用域鏈就是從當前作用域開始一層一層向上尋找某個變量,直到找到全局作用域還是沒找到,就宣布放棄。這種一層一層的關系,就是作用域鏈。
繼承(含es6)、多種繼承方式
(1)第一種是以原型鏈的方式來實現繼承,但是這種實現方式存在的缺點是,在包含有引用類型的數據時,會被所有的實例對象所共享,容易造成修改的混亂。還有就是在創建子類型的時候不能向超類型傳遞參數。
(2)第二種方式是使用借用構造函數的方式,這種方式是通過在子類型的函數中調用超類型的構造函數來實現的,這一種方法解決了不能向超類型傳遞參數的缺點,但是它存在的一個問題就是無法實現函數方法的復用,並且超類型原型定義的方法子類型也沒有辦法訪問到。
(3)第三種方式是組合繼承,組合繼承是將原型鏈和借用構造函數組合起來使用的一種方式。通過借用構造函數的方式來實現類型的屬性的繼承,通過將子類型的原型設置為超類型的實例來實現方法的繼承。這種方式解決了上面的兩種模式單獨使用時的問題,但是由於我們是以超類型的實例來作為子類型的原型,所以調用了兩次超類的構造函數,造成了子類型的原型中多了很多不必要的屬性。
(4)第四種方式是原型式繼承,原型式繼承的主要思路就是基於已有的對象來創建新的對象,實現的原理是,向函數中傳入一個對象,然后返回一個以這個對象為原型的對象。這種繼承的思路主要不是為了實現創造一種新的類型,只是對某個對象實現一種簡單繼承,ES5 中定義的 Object.create() 方法就是原型式繼承的實現。缺點與原型鏈方式相同。
(5)第五種方式是寄生式繼承,寄生式繼承的思路是創建一個用於封裝繼承過程的函數,通過傳入一個對象,然后復制一個對象的副本,然后對象進行擴展,最后返回這個對象。這個擴展的過程就可以理解是一種繼承。這種繼承的優點就是對一個簡單對象實現繼承,如果這個對象不是我們的自定義類型時。缺點是沒有辦法實現函數的復用。
(6)第六種方式是寄生式組合繼承,組合繼承的缺點就是使用超類型的實例做為子類型的原型,導致添加了不必要的原型屬性。寄生式組合繼承的方式是使用超類型的原型的副本來作為子類型的原型,這樣就避免了創建不必要的屬性。
EventLoop
JS是單線程的,為了防止一個函數執行時間過長阻塞后面的代碼,所以會先將同步代碼壓入執行棧中,依次執行,將異步代碼推入異步隊列,異步隊列又分為宏任務隊列和微任務隊列,因為宏任務隊列的執行時間較長,所以微任務隊列要優先於宏任務隊列。微任務隊列的代表就是,Promise.then,MutationObserver,宏任務的話就是setImmediate setTimeout setInterval
原生ajax
ajax是一種異步通信的方法,從服務端獲取數據,達到局部刷新頁面的效果。 過程:
1. 創建XMLHttpRequest對象;
2. 調用open方法傳入三個參數 請求方式(GET/POST)、url、同步異步(true/false);
3. 監聽onreadystatechange事件,當readystate等於4時返回responseText;
4. 調用send方法傳遞參數。
事件冒泡、捕獲(委托)
- 事件冒泡指在在一個對象上觸發某類事件,如果此對象綁定了事件,就會觸發事件,如果沒有,就會向這個對象的父級對象傳播,最終父級對象觸發了事件。
- 事件委托本質上是利用了瀏覽器事件冒泡的機制。因為事件在冒泡過程中會上傳到父節點,並且父節點可以通過事件對象獲取到目標節點,因此可以把子節點的監聽函數定義在父節點上,由父節點的監聽函數統一處理多個子元素的事件,這種方式稱為事件代理。
event.stopPropagation() 或者 ie下的方法 event.cancelBubble = true; //阻止事件冒泡
Vue
簡述MVVM
MVVM是Model-View-ViewModel縮寫,也就是把MVC中的Controller演變成ViewModel。Model層代表數據模型,View代表UI組件,ViewModel是View和Model層的橋梁,數據會綁定到viewModel層並自動將數據渲染到頁面中,視圖變化的時候會通知viewModel層更新數據。
談談對vue生命周期的理解?
每個Vue實例在創建時都會經過一系列的初始化過程,vue的生命周期鈎子,就是說在達到某一階段或條件時去觸發的函數,目的就是為了完成一些動作或者事件
- create階段:vue實例被創建 beforeCreate: 創建前,此時data和methods中的數據都還沒有初始化 created: 創建完畢,data中有值,未掛載
- mount階段: vue實例被掛載到真實DOM節點 beforeMount:可以發起服務端請求,去數據 mounted: 此時可以操作Dom
- update階段:當vue實例里面的data數據變化時,觸發組件的重新渲染 beforeUpdate updated
- destroy階段:vue實例被銷毀 beforeDestroy:實例被銷毀前,此時可以手動銷毀一些方法 destroyed
data為什么是一個函數而不是對象
因為對象是一個引用數據類型,如果data是一個對象的情況下會造成所有組件共用一個data。而當data是一個函數的情況下,每次函數執行完畢后都會返回一個新的對象,這樣的話每個組件都會維護一份獨立的對象(data)
computed與watch
watch 屬性監聽 是一個對象,鍵是需要觀察的屬性,值是對應回調函數,主要用來監聽某些特定數據的變化,從而進行某些具體的業務邏輯操作,監聽屬性的變化,需要在數據變化時執行異步或開銷較大的操作時使用
computed 計算屬性 屬性的結果會被緩存,當computed中的函數所依賴的屬性沒有發生改變的時候,那么調用當前函數的時候結果會從緩存中讀取。除非依賴的響應式屬性變化時才會重新計算,主要當做屬性來使用computed中的函數必須用return返回最終的結果 computed更高效,優先使用
使用場景 computed:當一個屬性受多個屬性影響的時候使用,例:購物車商品結算功能 watch:當一條數據影響多條數據的時候使用,例:搜索數據
v-for中key的作用
1. key的作用主要是為了更高效的對比虛擬DOM中每個節點是否是相同節點;
2. Vue在patch過程中判斷兩個節點是否是相同節點,key是一個必要條件,渲染一組列表時,key往往是唯一標識,所以如果不定義key的話,Vue只能認為比較的兩個節點是同一個,哪怕它們實際上不是,這導致了頻繁更新元素,使得整個patch過程比較低效,影響性能;
3. 從源碼中可以知道,Vue判斷兩個節點是否相同時主要判斷兩者的key和元素類型等,因此如果不設置key,它的值就是undefined,則可能永 遠認為這是兩個相同的節點,只能去做更新操作,這造成了大量的dom更新操作,明顯是不可取的。
vue組件的通信方式
父子組件通信
父->子props,子->父 $on、$emit` 獲取父子組件實例 parent、parent、children Ref 獲取實例的方式調用組件的屬性或者方法 Provide、inject` 官方不推薦使用,但是寫組件庫時很常用
兄弟組件通信
Event Bus 實現跨組件通信 Vue.prototype.$bus = new Vue() Vuex
跨級組件通信
$attrs、$listeners Provide、inject
路由傳參
1. 使用router-link進行路由導航,傳遞參數
2. 直接調用$router.push 實現攜帶參數的跳轉
3. 通過路由屬性中的name來確定匹配的路由,通過params來傳遞參數
4. 使用path來匹配路由,然后通過query來傳遞參數,這種情況下 query傳遞的參數會顯示在url
路由的兩種模式 hash與history
對於Vue 這類漸進式前端開發框架,為了構建SPA(單頁面應用),需要引入前端路由系統,這也就是Vue-router存在的意義。前端路由的核心,就在於改變視圖的同時不會向后端發出請求。
1、hash ——即地址欄URL中的#符號,它的特點在於:hash 雖然出現URL中,但不會被包含在HTTP請求中,對后端完全沒有影響,因此改變hash不會重新加載頁面。
2、history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法。這兩個方法應用於瀏覽器的歷史記錄站,在當前已有的back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改是,雖然改變了當前的URL,但你瀏覽器不會立即向后端發送請求。history模式,會出現404 的情況,需要后台配置。
路由守衛
雙向綁定實現原理
當一個Vue實例創建時,Vue會遍歷data選項的屬性,用 Object.defineProperty 將它們轉為 getter/setter並且在內部追蹤相關依賴,在屬性被訪問和修改時通知變化。每個組件實例都有相應的 watcher 程序實例,它會在組件渲染的過程中把屬性記錄為依賴,之后當依賴項的 setter 被調用時,會通知 watcher重新計算,從而致使它關聯的組件得以更新。
v-model的實現以及它的實現原理嗎?
1. vue中雙向綁定是一個指令v-model,可以綁定一個動態值到視圖,同時視圖中變化能改變該值。v-model是語法糖,默認情況下相於:value和@input。
2. 使用v-model可以減少大量繁瑣的事件處理代碼,提高開發效率,代碼可讀性也更好
3. 通常在表單項上使用v-model
4. 原生的表單項可以直接使用v-model,自定義組件上如果要使用它需要在組件內綁定value並處理輸入事件
5. 我做過測試,輸出包含v-model模板的組件渲染函數,發現它會被轉換為value屬性的綁定以及一個事件監聽,事件回調函數中會做相應變量更新操作,這說明神奇魔法實際上是vue的編譯器完成的。
new Vue后整個的流程
- initProxy:作用域代理,攔截組件內訪問其它組件的數據。
- initLifecycle:建立父子組件關系,在當前組件實例上添加一些屬性和生命周期標識。如[Math Processing Error]parent,parent,refs,$children,_isMounted等。
- initEvents:對父組件傳入的事件添加監聽,事件是誰創建誰監聽,子組件創建事件子組件監聽
- initRender:聲明[Math Processing Error]slots和slots和createElement()等。
- initInjections:注入數據,初始化inject,一般用於組件更深層次之間的通信。
- initState:重要)數據響應式:初始化狀態。很多選項初始化的匯總:data,methods,props,computed和watch。
- initProvide:提供數據注入。
思考:為什么先注入再提供呢??
1、首先來自祖輩的數據要和當前實例的data,等判重,相結合,所以注入數據的initInjections一定要在InitState的上面。
2. 從上面注入進來的東西在當前組件中轉了一下又提供給后代了,所以注入數據也一定要在上面。
keep-alive的實現
作用:實現組件緩存
鈎子函數:
`activated `組件渲染后調用
`deactivated `組件銷毀后調用
原理:Vue.js內部將DOM節點抽象成了一個個的VNode節點,keep-alive組件的緩存也是基於VNode節點的而不是直接存儲DOM結構。它將滿足條件(pruneCache與pruneCache)的組件在cache對象中緩存起來,在需要重新渲染的時候再將vnode節點從cache對象中取出並渲染。
配置屬性:
include 字符串或正則表達式。只有名稱匹配的組件會被緩存
exclude 字符串或正則表達式。任何名稱匹配的組件都不會被緩存
max 數字、最多可以緩存多少組件實例
vuex、vue-router實現原理
vuex是一個專門為vue.js應用程序開發的狀態管理庫。 核心概念:
- state(單一狀態樹) getter/Mutation顯示提交更改state
- Action類似Mutation,提交Mutation,可以包含任意異步操作。
- module(當應用變得龐大復雜,拆分store為具體的module模塊)
你怎么理解Vue中的diff算法?
在js中,渲染真實DOM的開銷是非常大的, 比如我們修改了某個數據,如果直接渲染到真實DOM, 會引起整個dom樹的重繪和重排。那么有沒有可能實現只更新我們修改的那一小塊dom而不要更新整個dom呢?此時我們就需要先根據真實dom生成虛擬dom, 當虛擬dom某個節點的數據改變后會生成有一個新的Vnode, 然后新的Vnode和舊的Vnode作比較,發現有不一樣的地方就直接修改在真實DOM上,然后使舊的Vnode的值為新的Vnode。
diff的過程就是調用patch函數,比較新舊節點,一邊比較一邊給真實的DOM打補丁。在采取diff算法比較新舊節點的時候,比較只會在同層級進行。 在patch方法中,首先進行樹級別的比較 new Vnode不存在就刪除 old Vnodeold Vnode 不存在就增加新的Vnode 都存在就執行diff更新 當確定需要執行diff算法時,比較兩個Vnode,包括三種類型操作:屬性更新,文本更新,子節點更新 新老節點均有子節點,則對子節點進行diff操作,調用updatechidren 如果老節點沒有子節點而新節點有子節點,先清空老節點的文本內容,然后為其新增子節點 如果新節點沒有子節點,而老節點有子節點的時候,則移除該節點的所有子節點 老新老節點都沒有子節點的時候,進行文本的替換
updateChildren 將Vnode的子節點Vch和oldVnode的子節點oldCh提取出來。 oldCh和vCh各有兩個頭尾的變量StartIdx和EndIdx,它們的2個變量相互比較,一共有4種比較方式。如果4種比較都沒匹配,如果設置了key,就會用key進行比較,在比較的過程中,變量會往中間靠,一旦StartIdx>EndIdx表明oldCh和vCh至少有一個已經遍歷完了,就會結束比較。
瀏覽器從輸入url到渲染頁面,發生了什么?
三個方面:
網絡篇:
1. 構建請求
2. 查找強緩存
3. DNS解析
4. 建立TCP連接(三次握手)
5. 發送HTTP請求(網絡請求后網絡響應)
瀏覽器解析篇:
1. 解析html構建DOM樹
2. 解析css構建CSS樹、樣式計算
3. 生成布局樹(Layout Tree)
瀏覽器渲染篇:
1. 建立圖層樹(Layer Tree)
2. 生成繪制列表
3. 生成圖塊並柵格化
4. 顯示器顯示內容
5. 最后斷開連接:TCP 四次揮手
Http和Https區別(高頻)
1.`HTTP` 是不安全的,而 HTTPS 是安全的
2.`HTTP` 標准端口是80 ,而 HTTPS 的標准端口是443
3.`HTTP` 無法加密,而HTTPS 對傳輸的數據進行加密
4.`HTTP`無需證書,而HTTPS 需要CA的SSL證書
GET和POST區別(高頻)
1.GET在瀏覽器回退不會再次請求,POST會再次提交請求
2.GET請求會被瀏覽器主動緩存,POST不會,要手動設置
3.GET請求參數會被完整保留在瀏覽器歷史記錄里,POST中的參數不會
4.GET請求在URL中傳送的參數是有長度限制的,而POST沒有限制
5.GET參數通過URL傳遞,POST放在Request body中
6.GET參數暴露在地址欄不安全,POST放在報文內部更安全
7.GET一般用於查詢信息,POST一般用於提交某種信息進行某些修改操作
8.GET產生一個TCP數據包;POST產生兩個TCP數據包
理解xss,csrf,ddos攻擊原理以及避免方式
XSS(Cross-Site Scripting,跨站腳本攻擊)是一種代碼注入攻擊。攻擊者在目標網站上注入惡意代碼,當被攻擊者登陸網站時就會執行這些惡意代碼,這些腳本可以讀取 cookie,session tokens,或者其它敏感的網站信息,對用戶進行釣魚欺詐,甚至發起蠕蟲攻擊等。
CSRF(Cross-site request forgery)跨站請求偽造:攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送跨站請求。利用受害者在被攻擊網站已經獲取的注冊憑證,繞過后台的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操作的目的。
XSS避免方式:
1. url參數使用encodeURIComponent方法轉義
2. 盡量不是有InnerHtml插入HTML內容
3. 使用特殊符號、標簽轉義符。
CSRF避免方式:
1. 添加驗證碼
2. 使用token
服務端給用戶生成一個token,加密后傳遞給用戶
用戶在提交請求時,需要攜帶這個token
服務端驗證token是否正確
http特性以及狀態碼
比如:
200響應成功
301永久重定向
302臨時重定向
304資源緩存
403服務器禁止訪問
404服務器資源未找到
500 502服務器內部錯誤
504 服務器繁忙
1xx Informational(信息狀態碼) 接受請求正在處理
2xx Success(成功狀態碼) 請求正常處理完畢
3xx Redirection(重定向狀態碼) 需要附加操作已完成請求
4xx Client Error(客戶端錯誤狀態碼) 服務器無法處理請求
5xx Server Error(服務器錯誤狀態碼) 服務器處理請求出錯復制代碼
http如何實現緩存
1. 強緩存==>Expires(過期時間)/Cache-Control(no-cache)(優先級高) 協商緩存 ==>Last-Modified/Etag(優先級高)Etag適用於經常改變的小文件 Last-Modefied適用於不怎么經常改變的大文件
2. 強緩存策略和協商緩存策略在緩存命中時都會直接使用本地的緩存副本,區別只在於協商緩存會向服務器發送一次請求。它們緩存不命中時,都會向服務器發送請求來獲取資源。在實際的緩存機制中,強緩存策略和協商緩存策略是一起合作使用的。瀏覽器首先會根據請求的信息判斷,強緩存是否命中,如果命中則直接使用資源。如果不命中則根據頭信息向服務器發起請求,使用協商緩存,如果協商緩存命中的話,則服務器不返回資源,瀏覽器直接使用本地資源的副本,如果協商緩存不命中,則瀏覽器返回最新的資源給瀏覽器。
什么是同源策略
一個域下的js腳本未經允許的情況下,不能訪問另一個域下的內容。通常判斷跨域的依據是協議、域名、端口號是否相同,不同則跨域。同源策略是對js腳本的一種限制,並不是對瀏覽器的限制,像img,script腳本請求不會有跨域限制。
前后端如何通信
Ajax : 短連接
Websocket : 長連接,雙向的。
Form表單:最原始的
跨域通信的幾種方式
解決方案:
1. jsonp(利用script標簽沒有跨域限制的漏洞實現。缺點:只支持GET請求)
2. CORS(設置Access-Control-Allow-Origin:指定可訪問資源的域名)
3. postMessage(message, targetOrigin, [transfer])(HTML5新增API 用於多窗口消息、頁面內嵌iframe消息傳遞),通過onmessage監聽 傳遞過來的數據
4. Websocket是HTML5的一個持久化的協議,它實現了瀏覽器與服務器的全雙工通信,同時也是跨域的一種解決方案。
5. Node中間件代理
6. Nginx反向代理
7. 各種嵌套iframe的方式,不常用。
8. 日常工作中用的最對的跨域方案是CORS和Nginx反向代理
前端工程化
webpack配置,webpack4.0有哪些優化點
module.exports={
entry: {},
output: {},
plugins: [],
module: [rules:[{}]]
}
webpack如何實現代碼分離
1.入口起點:使用 entry 配置手動地分離代碼。
2.防止重復:使用 CommonsChunkPlugin 去重和分離 chunk。
3.動態導入:通過模塊的內聯函數調用來分離代碼。
常見的Webpack Loader? 如何實現一個Webpack Loader(NO)
loader: 是一個導出為函數的javascript模塊,根據rule匹配文件擴展名,處理文件的轉換器。
file-loader:把文件輸出到一個文件夾中,在代碼中通過相對 URL 去引用輸出的文件 (處理圖片和字體)
url-loader: 與file-loader類似,區別是用戶可以設置一個閾值,大於閾值會交給file-loader處理,小於閾值時返回文件base64 形式編碼 (處理圖片和字體)
image-loader:加載並且壓縮圖片文件
babel-loader:把 ES6 轉換成 ES5
sass-loader:將SCSS/SASS代碼轉換成CSS
css-loader:加載 CSS,支持模塊化、壓縮、文件導入等特性
style-loader:把 CSS 代碼注入到 JavaScript 中,通過 DOM 操作去加載 CSS
postcss-loader:擴展 CSS 語法,使用下一代 CSS,可以配合 autoprefixer 插件自動補齊 CSS3 前綴 eslint-loader:通過 ESLint 檢查 JavaScript 代碼
常見的Webpack Plugin? 如何實現一個Webpack Plugin(NO)
plugin:本質是插件,基於事件流框架 Tapable,插件可以擴展 Webpack 的功能,在 Webpack 運行的生命周期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過 Webpack 提供的 API 改變輸出結果。
html-webpack-plugin:簡化 HTML 文件創建 (依賴於 html-loader)
uglifyjs-webpack-plugin:壓縮js文件
clean-webpack-plugin:目錄清除
mini-css-extract-plugin:分離樣式文件,CSS 提取為獨立文件,支持按需加載 (替代extract-text-webpack-plugin)
loader和plugin對比?
- Loader 在 module.rules 中配置,作為模塊的解析規則,類型為數組。每一項都是一個 Object,內部包含了 test(類型文件)、loader、options (參數)等屬性。
- Plugin 在 plugins 中單獨配置,類型為數組,每一項是一個Plugin的實例,參數都通過構造函數傳入。
前端模塊化,CMD、AMD、CommonJS
CommonJS
CommonJS是服務器端模塊的規范,由Node推廣使用,webpack也采用這種規范編寫
commonJs規范:
CommonJS模塊規范主要分為三部分:模塊定義、模塊標識、模塊引用。
模塊定義:module對象:在每一個模塊中,module對象代表該模塊自身。 export屬性:module對象的一個屬性,它向外提供接口。輸出模塊變量的最好方法是使用module.exports對象。一個單獨的文件就是一個模塊。每一個模塊都是一個單獨的作用域,也就是說,在該模塊內部定義的變量,無法被其他模塊讀取,除非定義為global對象的屬性。
模塊標識:傳遞給require方法的參數,必須是符合小駝峰命名的字符串,或者以 . 、.. 、開頭的相對路徑,或者絕對路徑。
模塊引用:加載模塊使用require(同步加載),該方法讀取一個文件並執行,返回文件內部的module.exports對象。
優勢:
在后端,JavaScript的規范遠遠落后並且有很多缺陷,這使得難以使用JavaScript開發大型應用。比如:沒有模塊系統、標准庫較少、沒有標准接口、缺乏包管理系統、列表內容
CommonJS模塊規范很好地解決變量污染問題,每個模塊具有獨立空間,互不干擾,命名空間相比之下就不太好。
CommonJS規范定義模塊十分簡單,接口十分簡潔。
CommonJS模塊規范支持引入和導出功能,這樣可以順暢地連接各個模塊,實現彼此間的依賴關系
CommonJS規范的提出,主要是為了彌補JavaScript沒有標准的缺陷,已達到像Python、Ruby和Java那樣具備開發大型應用的基礎能力,而不是停留在開發瀏覽器端小腳本程序的階段
缺點:
沒有並行加載機制
由於CommonJS是同步加載模塊,這對於服務器端是很不好的,因為所有的模塊都放在本地硬盤。等待模塊時間就是硬盤讀取文件時間,很小。但是,對於瀏覽器而言,它需要從服務器加載模塊,涉及到網速,代理等原因,一旦等待時間過長,瀏覽器處於”假死”狀態。
所以瀏覽器端不是很適合Common.Js,出現另一種規范AMD
AMD
AMD 是運行在瀏覽器環境的一個異步模塊定義規范 ,是RequireJS 在推廣過程中對模塊定義的規范化產出。
AMD規范
AMD推崇依賴前置,在定義模塊的時候就要聲明其依賴的模塊
優點
用戶體驗好,因為沒有延遲,依賴模塊提前執行了。
CMD
CMD是一個通用模塊定義規范;是SeaJs推廣過程中對模塊定義的規范化產出
CMD規范
CMD推崇依賴就近,只有在用到某個模塊的時候才會去require
優點
性能好,因為只有用戶需要的時候才執行。
防抖節流
函數防抖關注一定時間連續觸發,只在最后執行一次,而函數節流側重於一段時間內只執行一次。
防抖
//定義:觸發事件后在n秒內函數只能執行一次,如果在n秒內又觸發了事件,則會重新計算函數執行時間。
//搜索框搜索輸入。只需用戶最后一次輸入完,再發送請求
//手機號、郵箱驗證輸入檢測 onchange oninput事件
//窗口大小Resize。只需窗口調整完成后,計算窗口大小。防止重復渲染。更多》》
const debounce = (fn, wait, immediate) => {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
if (immediate && !timer) {
fn.call(this, args);
}
timer = setTimeout(() => {
fn.call(this, args);
}, wait); }; };
const betterFn = debounce(() => console.log("fn 防抖執行了"), 1000, true);
document.addEventListener("scroll", betterFn);
節流
//定義:當持續觸發事件時,保證隔間時間觸發一次事件。//1. 懶加載、滾動加載、加載更多或監聽滾動條位置;//2. 百度搜索框,搜索聯想功能;//3. 防止高頻點擊提交,防止表單重復提交;更多》》
function throttle(fn,wait){
let pre = 0; return function(...args){ let now = Date.now(); if( now - pre >= wait){ fn.apply(this,args); pre = now; } } }function handle(){ console.log(Math.random()); }window.addEventListener("mousemove",throttle(handle,1000));
對象深淺拷貝
//淺拷貝
1. Object.assign(target,source)
2. es6對象擴展運算符。
//深拷貝
function deepClone(obj) { if (!obj || typeof obj !== "object") return; let newObj = Array.isArray(obj) ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] === "object" ? deepClone(obj[key]) : obj[key]; } } return newObj; }
數組去重,數組對象去重
//數組 const arr = [2,7,5,7,2,8,9]; console.log([...new Set(arr)]);// [2,7,5,8,9]; //對象 const list = [{age:18,name:'張三'},{age:18,name:'李四'},{age:18,name:'王五'}] let hash = {}; const newArr = arr.reduce((item, next) => { hash[next.age] ? '' : hash[next.age] = true && item.push(next); return item; }, []);console.log(list);
數組扁平化
function flatten(arr) { return arr.reduce((result, item) => { return result.concat(Array.isArray(item) ? flatten(item) : item); }, []); }
你都做過哪些Vue的性能優化?
編碼階段
盡量減少data中的數據,data中的數據都會增加getter和setter,會收集對應的watcher
v-if和v-for不能連用
如果需要使用v-for給每項元素綁定事件時使用事件代理
SPA 頁面采用keep-alive緩存組件
在更多的情況下,使用v-if替代v-show
key保證唯一
使用路由懶加載、異步組件
防抖、節流
第三方模塊按需導入
長列表滾動到可視區域動態加載
圖片懶加載
SEO優化
預渲染
服務端渲染SSR
打包優化
壓縮代碼
Tree Shaking/Scope Hoisting
使用cdn加載第三方模塊
多線程打包happypack
splitChunks抽離公共文件
sourceMap優化
用戶體驗
骨架屏
PWA
還可以使用緩存(客戶端緩存、服務端緩存)優化、服務端開啟gzip壓縮等。
寫的比較匆忙,可能有諸多問題,望各位大佬指正。