Ⅰ vue和react的diff演算法比較
相同點:
Vue和react的diff演算法,都是不進行跨層級比較,只做同級比較。
不同點:
1.Vue進行diff時,調用patch打補丁函數,一邊比較一邊給真實的DOM打補丁
2.Vue對比節點,當節點元素類型相同,但是className不同時,認為是不同類型的元素,刪除重新創建,而react則認為是同類型節點,進行修改操作
3.① Vue的列表比對,採用從兩端到中間的方式,舊集合和新集合兩端各存在兩個指針,兩兩進行比較,如果匹配上了就按照新集合去調整舊集合,每次對比結束後,指針向隊列中間移動;
②而react則是從左往右依次對比,利用元素的index和標識lastIndex進行比較,如果滿足index < lastIndex就移動元素,刪除和添加則各自按照規則調整;
③當一個集合把最後一個節點移動到最前面,react會把前面的節點依次向後移動,而Vue只會把最後一個節點放在最前面,這樣的操作來看,Vue的diff性能是高於react的
Ⅱ diff演算法是什麼
diff演算法是虛擬DOM中採用的演算法。
把樹形結構按照層級分解,只比較同級元素。不同層級的節點只有創建和刪除操作。給列表結構的每個單元添加唯一的key屬性,方便比較。
相關信息:
React只會匹配相同class的component。合並操作,調用component 的 setState 方法的時候,React將其標記為dirty。
到每一個事件循環結束,React 檢查所有標記 dirty 的 component 重新繪制。選擇性子樹渲染。開發人員可以重寫 shouldComponentUpdate 提高 diff 的性能。
Ⅲ 面試中的網紅Vue源碼解析之虛擬DOM,你知多少呢深入解讀diff演算法
眾所周知,在前端的面試中,面試官非常愛考dom和diff演算法。比如,可能會出現在以下場景
滴滴滴,面試官發來一個面試邀請。接受邀請📞
我們都知道, key 的作用在前端的面試是一道很普遍的題目,但是呢,很多時候我們都只浮於知識的表面,而沒有去深挖其原理所在,這個時候我們的競爭力就在這被拉下了。所以呢,深入學習原理對於提升自身的核心競爭力是一個必不可少的過程。
在接下來的這篇文章中,我們將講解面試中很愛考的虛擬DOM以及其背後的diff演算法。 請認真閱讀本文~文末有學習資源免費共享!!!
虛擬DOM是用JavaScript對象描述DOM的層次結構。DOM中的一切屬性都在虛擬DOM中有對應的屬性。本質上是JS 和 DOM 之間的一個映射緩存。
要點:虛擬 DOM 是 JS 對象;虛擬 DOM 是對真實 DOM 的描述。
diff發生在虛擬DOM上。diff演算法是在新虛擬DOM和老虛擬DOM進行diff(精細化比對),實現最小量更新,最後反映到真正的DOM上。
我們前面知道diff演算法發生在虛擬DOM上,而虛擬DOM是如何實現的呢?實際上虛擬DOM是有一個個虛擬節點組成。
h函數用來產生虛擬節點(vnode)。虛擬節點有如下的屬性:
1)sel: 標簽類型,例如 p、div;
2)data: 標簽上的數據,例如 style、class、data-*;
3)children :子節點;
4) text: 文本內容;
5)elm:虛擬節點綁定的真實 DOM 節點;
通過h函數的嵌套,從而得到虛擬DOM樹。
我們編寫了一個低配版的h函數,必須傳入3個參數,重載較弱。
形態1:h('div', {}, '文字')
形態2:h('div', {}, [])
形態3:h('div', {}, h())
首先定義vnode節點,實際上就是把傳入的參數合成對象返回。
[圖片上傳失敗...(image-7a9966-1624019394657)]
然後編寫h函數,根據第三個參數的不同進行不同的響應。
當我們進行比較的過程中,我們採用的4種命中查找策略:
1)新前與舊前:命中則指針同時往後移動。
2)新後與舊後:命中則指針同時往前移動。
3)新後與舊前:命中則涉及節點移動,那麼新後指向的節點,移到 舊後之後 。
4)新前與舊後:命中則涉及節點移動,那麼新前指向的節點,移到 舊前之前 。
命中上述4種一種就不在命中判斷了,如果沒有命中,就需要循環來尋找,移動到舊前之前。直到while(新前<=新後&&舊前<=就後)不成立則完成。
如果是新節點先循環完畢,如果老節點中還有剩餘節點(舊前和舊後指針中間的節點),說明他們是要被刪除的節點。
如果是舊節點先循環完畢,說明新節點中有要插入的節點。
1.什麼是Virtual DOM 和Snabbdom
2.手寫底層源碼h函數
3.感受Vue核心演算法之diff演算法
4.snabbdom之核心h函數的工作原理
1、零基礎入門或者有一定基礎的同學、大中院校學生
2、在職從事相關工作1-2年以及打算轉行前端的朋友
3、對前端開發有興趣人群
Ⅳ vue-diff演算法
渲染真實DOM的開銷是很大的,輕微的操作都可能導致頁面重新排版,非常耗性能。 相對於DOM對象,js對象處理起來更快,而且更簡單。 通過diff演算法對比新舊vdom之間的差異,可以批量的、最小化的執行 dom操作,從而提高性能。
常規:O(n^3) 遍歷樹1; 遍歷樹2; 排序; 1000個節點,十億的量級。
vue diff:O(n) 只比較同一層級 ;tag不相同,直接刪掉重建; 通過key來標識區分相同節點。
舊節點:A、B、C、D
新節點:A、E、B、C、D
1.1 兩個節點key是否相同(兩個key都沒有,即 undefined === undefined)
1.2 兩個節點tag標簽名是否一樣
1.3 兩個節點是否都為注釋節點
1.4 兩個節點的data isDef是否都相等(isDef:data !== undefined && data !== null)
1.5 兩個節點的input類型是否相同
1.6 節點a是否為非同步佔位
1.7 兩個節點的非同步函數是否相等
1.8節點b非同步函數的error是否為空(isUndef:data === undefined && data === null)
2.1 新舊節點都有子節點,調用updateChildren重排子節點
2.2 只有新節點有子節點,調用addVnodes添加子節點
2.3 只有舊節點有子節點,調用removeVnodes移除子節點
2.4 如果是文本節點,調用setTextContent更新節點文本內容
3.1.1 舊頭不存在,將舊頭游標往後移一位
3.1.2 舊尾不存在,將舊尾游標往前移一位
3.1.3 舊頭、新頭相同,更新節點,並將頭部游標往後移一位
3.1.4 舊尾、新尾相同,更新節點,並將尾部游標往前移一位
3.1.5 舊頭、新尾相同,更新節點,並且將舊頭移到尾部,舊頭游標往後移一位,新尾游標往前移一位
3.1.6 舊尾、新頭相同,更新節點,並且將舊尾移到頭部,新頭游標往後移一位,舊尾游標往前移一位
3.1.7 拿新頭遍歷舊子節點,找不到則新建一個節點;找到判斷節點是否相同,相同則更新節點,移動老節點,不同則新建一個節點
3.2.1 舊子節點先遍歷完畢,說明有新增節點,批量增加
3.2.2 新子節點先遍歷完畢,說明有節點刪除,批量移除
Ⅳ 整理涵蓋很全很廣的前端知識點
HTML、CSS相關
html5新特性、語義化
瀏覽器渲染機制、重繪、重排
網頁生成過程:
重排(也稱迴流): 當 DOM 的變化影響了元素的幾何信息( DOM 對象的位置和尺寸大小),瀏覽器需要重新計算元素的幾何屬性,將其安放在界面中的正確位置,這個過程叫做重排。 觸發:
重繪: 當一個元素的外觀發生改變,但沒有改變布局,重新把元素外觀繪制出來的過程,叫做重繪。 觸發:
重排優化建議:
transform 不重繪,不迴流 是因為 transform 屬於合成屬性,對合成屬性進行 transition/animate 動畫時,將會創建一個合成層。這使得動畫元素在一個獨立的層中進行渲染。當元素的內容沒有發生改變,就沒有必要進行重繪。瀏覽器會通過重新復合來創建動畫幀。
css盒子模型
所有 HTML 元素可以看作盒子,在CSS中, "box model" 這一術語是用來設計和布局時使用。 CSS 盒模型本質上是一個盒子,封裝周圍的 HTML 元素,它包括:邊距,邊框,填充,和實際內容。 盒模型允許我們在其它元素和周圍元素邊框之間的空間放置元素。
css樣式優先順序
!important>style>id>class
什麼是BFC?BFC的布局規則是什麼?如何創建BFC?BFC應用?
BFC 是 Block Formatting Context 的縮寫,即塊格式化上下文。 BFC 是CSS布局的一個概念,是一個環境,裡面的元素不會影響外面的元素。 布局規則:Box是CSS布局的對象和基本單位,頁面是由若干個Box組成的。元素的類型和display屬性,決定了這個Box的類型。不同類型的Box會參與不同的 Formatting Context 。 創建:浮動元素 display:inline-block position:absolute 應用: 1.分屬於不同的 BFC 時,可以防止 margin 重疊 2.清除內部浮動 3.自適應多欄布局
DOM、BOM對象
BOM(Browser Object Model) 是指瀏覽器對象模型,可以對瀏覽器窗口進行訪問和操作。使用 BOM,開發者可以移動窗口、改變狀態欄中的文本以及執行其他與頁面內容不直接相關的動作。 使 JavaScript 有能力與瀏覽器"對話"。 DOM (Document Object Model) 是指文檔對象模型,通過它,可以訪問 HTML 文檔的所有元素。 DOM 是 W3C (萬維網聯盟)的標准。 DOM 定義了訪問 HTML 和 XML 文檔的標准: "W3C 文檔對象模型(DOM)是中立於平台和語言的介面,它允許程序和腳本動態地訪問和更新文檔的內容、結構和樣式。" W3C DOM 標准被分為 3 個不同的部分:
什麼是 XML DOM ? XML DOM 定義了所有 XML 元素的對象和屬性,以及訪問它們的方法。 什麼是 HTML DOM? HTML DOM 定義了所有 HTML 元素的對象和屬性,以及訪問它們的方法。
JS相關
js數據類型、typeof、instanceof、類型轉換
閉包(高頻)
閉包是指有權訪問另一個函數作用域中的變數的函數 ——《JavaScript高級程序設計》
當函數可以記住並訪問所在的詞法作用域時,就產生了閉包,
即使函數是在當前詞法作用域之外執行 ——《你不知道的JavaScript》
原型、原型鏈(高頻)
原型: 對象中固有的 __proto__ 屬性,該屬性指向對象的 prototype 原型屬性。
原型鏈: 當我們訪問一個對象的屬性時,如果這個對象內部不存在這個屬性,那麼它就會去它的原型對象里找這個屬性,這個原型對象又會有自己的原型,於是就這樣一直找下去,也就是原型鏈的概念。原型鏈的盡頭一般來說都是 Object.prototype 所以這就是我們新建的對象為什麼能夠使用 toString() 等方法的原因。
特點: JavaScript 對象是通過引用來傳遞的,我們創建的每個新對象實體中並沒有一份屬於自己的原型副本。當我們修改原型時,與之相關的對象也會繼承這一改變。
this指向、new關鍵字
this 對象是是執行上下文中的一個屬性,它指向最後一次調用這個方法的對象,在全局函數中, this 等於 window ,而當函數被作為某個對象調用時,this等於那個對象。 在實際開發中, this 的指向可以通過四種調用模式來判斷。
new
作用域、作用域鏈、變數提升
繼承(含es6)、多種繼承方式
(1)第一種是以 原型鏈的方式來實現繼承 ,但是這種實現方式存在的缺點是,在包含有引用類型的數據時,會被所有的實例對象所共享,容易造成修改的混亂。還有就是在創建子類型的時候不能向超類型傳遞參數。
(2)第二種方式是使用 借用構造函數 的方式,這種方式是通過在子類型的函數中調用超類型的構造函數來實現的,這一種方法解決了不能向超類型傳遞參數的缺點,但是它存在的一個問題就是無法實現函數方法的復用,並且超類型原型定義的方法子類型也沒有辦法訪問到。
(3)第三種方式是 組合繼承 ,組合繼承是將原型鏈和借用構造函數組合起來使用的一種方式。通過借用構造函數的方式來實現類型的屬性的繼承,通過將子類型的原型設置為超類型的實例來實現方法的繼承。這種方式解決了上面的兩種模式單獨使用時的問題,但是由於我們是以超類型的實例來作為子類型的原型,所以調用了兩次超類的構造函數,造成了子類型的原型中多了很多不必要的屬性。
(4)第四種方式是 原型式繼承 ,原型式繼承的主要思路就是基於已有的對象來創建新的對象,實現的原理是,向函數中傳入一個對象,然後返回一個以這個對象為原型的對象。這種繼承的思路主要不是為了實現創造一種新的類型,只是對某個對象實現一種簡單繼承,ES5 中定義的 Object.create() 方法就是原型式繼承的實現。缺點與原型鏈方式相同。
(5)第五種方式是 寄生式繼承 ,寄生式繼承的思路是創建一個用於封裝繼承過程的函數,通過傳入一個對象,然後復制一個對象的副本,然後對象進行擴展,最後返回這個對象。這個擴展的過程就可以理解是一種繼承。這種繼承的優點就是對一個簡單對象實現繼承,如果這個對象不是我們的自定義類型時。缺點是沒有辦法實現函數的復用。
(6)第六種方式是 寄生式組合繼承 ,組合繼承的缺點就是使用超類型的實例做為子類型的原型,導致添加了不必要的原型屬性。寄生式組合繼承的方式是使用超類型的原型的副本來作為子類型的原型,這樣就避免了創建不必要的屬性。
EventLoop
JS 是單線程的,為了防止一個函數執行時間過長阻塞後面的代碼,所以會先將同步代碼壓入執行棧中,依次執行,將非同步代碼推入非同步隊列,非同步隊列又分為宏任務隊列和微任務隊列,因為宏任務隊列的執行時間較長,所以微任務隊列要優先於宏任務隊列。微任務隊列的代表就是, Promise.then , MutationObserver ,宏任務的話就是 setImmediate setTimeout setInterval
原生ajax
ajax 是一種非同步通信的方法,從服務端獲取數據,達到局部刷新頁面的效果。 過程:
事件冒泡、捕獲(委託)
event.stopPropagation() 或者 ie下的方法 event.cancelBubble = true; //阻止事件冒泡
ES6
Vue
簡述MVVM
MVVM 是 Model-View-ViewModel 縮寫,也就是把 MVC 中的 Controller 演變成 ViewModel。Model 層代表數據模型, View 代表UI組件, ViewModel 是 View 和 Model 層的橋梁,數據會綁定到 viewModel 層並自動將數據渲染到頁面中,視圖變化的時候會通知 viewModel 層更新數據。
談談對vue生命周期的理解?
每個 Vue 實例在創建時都會經過一系列的初始化過程, vue 的生命周期鉤子,就是說在達到某一階段或條件時去觸發的函數,目的就是為了完成一些動作或者事件
computed與watch
watch 屬性監聽 是一個對象,鍵是需要觀察的屬性,值是對應回調函數,主要用來監聽某些特定數據的變化,從而進行某些具體的業務邏輯操作,監聽屬性的變化,需要在數據變化時執行非同步或開銷較大的操作時使用
computed 計算屬性 屬性的結果會被緩存,當 computed 中的函數所依賴的屬性沒有發生改變的時候,那麼調用當前函數的時候結果會從緩存中讀取。除非依賴的響應式屬性變化時才會重新計算,主要當做屬性來使用 computed 中的函數必須用 return 返回最終的結果 computed 更高效,優先使用
使用場景 computed :當一個屬性受多個屬性影響的時候使用,例:購物車商品結算功能 watch :當一條數據影響多條數據的時候使用,例:搜索數據
v-for中key的作用
vue組件的通信方式
父子組件通信
父->子 props ,子->父 $on、$emit` 獲取父子組件實例 parent、 parent 、children Ref 獲取實例的方式調用組件的屬性或者方法 Provide、inject` 官方不推薦使用,但是寫組件庫時很常用
兄弟組件通信
Event Bus 實現跨組件通信 Vue.prototype.$bus = new Vue() Vuex
跨級組件通信
$attrs、$listeners Provide、inject
常用指令
雙向綁定實現原理
當一個 Vue 實例創建時,Vue會遍歷data選項的屬性,用 Object.defineProperty 將它們轉為 getter/setter並且在內部追蹤相關依賴,在屬性被訪問和修改時通知變化。每個組件實例都有相應的 watcher 程序實例,它會在組件渲染的過程中把屬性記錄為依賴,之後當依賴項的 setter 被調用時,會通知 watcher重新計算,從而致使它關聯的組件得以更新。
v-model的實現以及它的實現原理嗎?
nextTick的實現
vnode的理解,compiler和patch的過程
new Vue後整個的流程
思考:為什麼先注入再提供呢??
答:1、首先來自祖輩的數據要和當前實例的data,等判重,相結合,所以注入數據的initInjections一定要在 InitState 的上面。2. 從上面注入進來的東西在當前組件中轉了一下又提供給後代了,所以注入數據也一定要在上面。
vm.[Math Processing Error]mount(vm.mount(vm.options.el) :掛載實例。
keep-alive的實現
作用:實現組件緩存
鉤子函數:
原理: Vue.js 內部將 DOM 節點抽象成了一個個的 VNode 節點, keep-alive 組件的緩存也是基於 VNode 節點的而不是直接存儲 DOM 結構。它將滿足條件 (pruneCache與pruneCache) 的組件在 cache 對象中緩存起來,在需要重新渲染的時候再將 vnode 節點從 cache 對象中取出並渲染。
配置屬性:
include 字元串或正則表達式。只有名稱匹配的組件會被緩存
exclude 字元串或正則表達式。任何名稱匹配的組件都不會被緩存
max 數字、最多可以緩存多少組件實例
vuex、vue-router實現原理
vuex 是一個專門為vue.js應用程序開發的狀態管理庫。 核心概念:
你怎麼理解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 Vnode old 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 至少有一個已經遍歷完了,就會結束比較。
你都做過哪些Vue的性能優化?
你知道Vue3有哪些新特性嗎?它們會帶來什麼影響?
更小巧、更快速 支持自定義渲染器 支持搖樹優化:一種在打包時去除無用代碼的優化手段 支持Fragments和跨組件渲染
模板語法99%保持不變 原生支持基於class的組件,並且無需藉助任何編譯及各種stage階段的特性 在設計時也考慮TypeScript的類型推斷特性 重寫虛擬DOM 可以期待更多的編譯時提示來減少運行時的開銷 優化插槽生成 可以單獨渲染父組件和子組件 靜態樹提升 降低渲染成本 基於Proxy的觀察者機制 節省內存開銷
檢測機制 更加全面、精準、高效,更具可調試式的響應跟蹤
實現雙向綁定 Proxy 與 Object.defineProperty 相比優劣如何?
React
1、react中key的作用,有key沒key有什麼區別,比較同一層級節點什麼意思?
2、你對虛擬dom和diff演算法的理解,實現render函數
虛擬DOM 本質上是 JavaScript 對象,是對 真實DOM 的抽象表現。 狀態變更時,記錄新樹和舊樹的差異 最後把差異更新到真正的 dom 中 render函數:
3、React組件之間通信方式?
Context 提供了一個無需為每層組件手動添加 props ,就能在組件樹間進行數據傳遞的方法.如果你只是想避免層層傳遞一些屬性,組件組合( component composition )有時候是一個比 context 更好的解決方案。 5. 組件組合缺點:會使高層組件變得復雜
4、如何解析jsx
5、生命周期都有哪幾種,分別是在什麼階段做哪些事情?為什麼要廢棄一些生命周期?
componentWillMount、componentWillReceiveProps、componentWillUpdate在16版本被廢棄,在17版本將被刪除,需要使用UNSAVE_前綴使用,目的是向下兼容。
6、關於react的優化方法
使用return null而不是CSS的display:none來控制節點的顯示隱藏。保證同一時間頁面的DOM節點盡可能的少。
不要使用數組下標作為key 利用 shouldComponentUpdate 和 PureComponent 避免過多 render function ; render 裡面盡量減少新建變數和bind函數,傳遞參數是盡量減少傳遞參數的數量。 盡量將 props 和 state 扁平化,只傳遞 component 需要的 props (傳得太多,或者層次傳得太深,都會加重 shouldComponentUpdate 裡面的數據比較負擔),慎將 component 當作 props 傳入
使用 babel-plugin-import 優化業務組件的引入,實現按需載入 使用 SplitChunksPlugin 拆分公共代碼 使用動態 import ,懶載入 React 組件
7、綁定this的幾種方式
8、對fiber的理解
9、setState是同步還是非同步的
10、Rex、React-Rex
Rex的實現流程
用戶頁面行為觸發一個 Action ,然後 Store 調用 Recer ,並且傳入兩個參數:當前 State 和收到的 Action 。 Recer 會返回新的 State 。每當 state 更新之後, view 會根據 state 觸發重新渲染。
React-Rex:
Provider :從最外部封裝了整個應用,並向 connect 模塊傳遞 store 。 Connect :
11、對高階組件的理解
高階組件是參數為組件,返回值為新組件的函數。 HOC 是純函數,沒有副作用。 HOC 在 React 的第三方庫中很常見,例如 Rex 的 connect 組件。
高階組件的作用:
12、可以用哪些方式創建 React 組件?
React.createClass()、ES6 class 和無狀態函數
13、 React 元素與組件的區別?
組件是由元素構成的。元素數據結構是普通對象,而組件數據結構是類或純函數。
Vue與React對比?
數據流:
react 主張函數式編程,所以推崇純組件,數據不可變,單向數據流,
vue 的思想是響應式的,也就是基於是數據可變的,通過對每一個屬性建立Watcher來監聽,當屬性變化的時候,響應式的更新對應的虛擬dom。
監聽數據變化實現原理 :
組件通信的區別:jsx和.vue模板。
性能優化
vuex 和 rex 之間的區別?
從實現原理上來說,最大的區別是兩點:
Rex 使用的是不可變數據,而 Vuex 的數據是可變的。 Rex 每次都是用新的 state 替換舊的 state ,而 Vuex 是直接修改
Rex 在檢測數據變化的時候,是通過 diff 的方式比較差異的,而 Vuex 其實和Vue的原理一樣,是通過 getter/setter 來比較的(如果看 Vuex 源碼會知道,其實他內部直接創建一個 Vue 實例用來跟蹤數據變化)
瀏覽器從輸入url到渲染頁面,發生了什麼?
網路安全、HTTP協議
TCP UDP 區別
Http和Https區別(高頻)
GET和POST區別(高頻)
理解xss,csrf,ddos攻擊原理以及避免方式
XSS ( Cross-Site Scripting , 跨站腳本攻擊 )是一種代碼注入攻擊。攻擊者在目標網站上注入惡意代碼,當被攻擊者登陸網站時就會執行這些惡意代碼,這些腳本可以讀取 cookie,session tokens ,或者其它敏感的網站信息,對用戶進行釣魚欺詐,甚至發起蠕蟲攻擊等。
CSRF ( Cross-site request forgery ) 跨站請求偽造 :攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送跨站請求。利用受害者在被攻擊網站已經獲取的注冊憑證,繞過後台的用戶驗證,達到冒充用戶對被攻擊的網站執行某項操作的目的。
XSS避免方式:
CSRF 避免方式:
DDoS 又叫分布式拒絕服務,全稱 Distributed Denial of Service ,其原理就是利用大量的請求造成資源過載,導致服務不可用。
Ⅵ 簡單幾句話,知道什麼是迴流重繪、vue虛擬dom、diff演算法和key
1.什麼是vue虛擬dom。先知道什麼是dom樹。
眾所周知,一個頁面形成的流程。(順便聊一下迴流和重繪)
(1) 解析 HTML===>生成DOM樹
(2) 解析CSS===>生成CSSDOM樹
(3) Render Tree ===> 從Dom樹的根節點開始遍歷每個可見的節點(因為這裡面有display:none、scrpi等的,不被遍歷。)
對於每個可見的節點,找到其對應的CSSDOM規則,並且應用。
生成Render Tree 。
fine,問題來了,什麼是迴流呢?就是在生成render Tree 的時候,有的CSS涉及到了HTML的尺寸(width/height)、布局改變、隱藏等。詳細的可以去搜一下怎麼會造成迴流。<h3>所有的頁面都至少會有一次迴流,因為第一次生成render tree一定會迴流</h3>
Render Tree生成後,layout(布局)就完成了開始繪制(添加屬性,類似於顏色啊,大小啊之類的不會影響布局的屬性)。如果說不出意外你不去改的話這輩子和個Render Tree就永遠是這個樹了。HTML頁面就渲染結束了。
但是如果你想改。好嘛,我們就要開始判斷你改的是什麼了。如果說是影響布局的,那就是迴流===>重繪
如果說你只想改個顏色啥的那就直接是重繪,沒有迴流。
<h3>傑倫:迴流必然會帶來重繪,但是重繪不一定會迴流</h3>
關於如何優化,可以搜索迴流和重繪
參考圖:
好了,簡單的理解了一些html解析和dom樹的生成流程。就可以解釋什麼是虛擬dom了。
虛擬dom也還是那個dom。那為啥不用真實的dom呢?因為真實的DOM你一操作,它立馬給你迴流重繪,可能你有10個事件在等著干,一個個都要迴流重繪一遍太影響性能了。
(高光打過來!)虛擬dom就站出來了。
虛擬dom:如果有10次更新dom的動作,虛擬dom不會立即操作dom,而是將這10次更新的內容儲存起來,通過diff演算法,把新的dom(vue剛構造的虛擬dom)和舊的dom(可能是頁面上現在顯示的真實的dom)進行對比。然後渲染對比完的DOM。
問題來了:什麼是diff呢?這是一個演算法,有興趣的可以自己搜一下詳細了解誒。我這里只是簡單的介紹說這個東西就是 :頭頭對比。肚子肚子對比。腳腳對比。同級對比,不會跨級對比。就是我的新頭和我的舊頭對比。我的新肚子和我的舊肚子對比。對比完了去頁面上生成一個新的我。
上面提到了patch階段,順便說一下key diff演算法會通過key可以判斷這兩個虛擬dom是不是同一個dom,所以我們key盡量都要寫上,並且盡量不要使用索引作為key。可以使用 'xx-index' 方式寫key。方便你我它~~
好了。本文over 以上都是自己復習的時候總結的內容,如果有問題請留言 Thanks♪(・ω・)ノ
Ⅶ vue 中的虛擬dom樹
當頁面渲染的時候Vue會創建一顆虛擬DOM樹
當頁面發生改變Vue會再創建一顆新的虛擬DOM樹
前後兩顆新舊虛擬DOM樹進行對比,Vue通過diff演算法,去記錄差異的地方
將有差異的地方更新到真實的DOM樹中
vue中的虛擬DOM樹只會重新渲染頁面修改的地方,大大減少了對真實DOM樹的操作。 -------虛擬DOM樹是占內容的,但是可以幫我們提高DOM的性能。
可以這樣理解,虛擬DOM樹占空間,,,虛擬DOM樹可以提高DOM效率,,節省時間。
vue不直接操作真實的DOM樹,通過虛擬DOM樹就可以重新渲染修改的地方,重要的支撐就是 diff 演算法。
key的作用是為了高效的更新虛擬DOM樹,提高查找的效率,可以快速的查找到要修改的元素
Ⅷ vue頁面的渲染過程
我們從最簡單的new Vue開始:
1、new Vue,執行初始化
2、掛載$mount方法,通過自定義Render方法、template、el等生成Render函數
3、通過Watcher監聽數據的變化
4、當數據發生變化時,Render函數執行生成VNode對象
5、通過patch方法,對比新舊VNode對象,通過DOM Diff演算法,添加、修改、刪除真正的DOM元素
至此,整個new Vue的渲染過程完畢。
1、把模板編譯為render函數
2、實例進行掛載, 根據根節點render函數的調用,遞歸的生成虛擬dom
3、對比虛擬dom,渲染到真實dom
4、組件內部data發生變化,組件和子組件引用data作為props重新調用render函數,生成虛擬dom, 返回到步驟3
詳見鏈接: https://segmentfault.com/a/1190000018495383
Ⅸ 徹底理解vue的patch流程和diff演算法
上一篇 《vue非同步更新流程梳理》 梳理了數據從賦值到更新到視圖的整體流程。但是最後的步驟 vm._update(vm._render()) 只是粗略的提了一嘴,現在就仔細的研究它內部的細節,搞清楚patch流程和diff原理是我們看源碼的重中之重。
當更新數據的時候就會執行這個updateComponent方法,即方法裡面的 vm._update(vm._render()) ,vm.render() 得到一個vnode,那麼vm._update到底干什麼? 進去看看
至此,無論是初始化還是更新都是靠patch來完成的 ,我們只需要看update流程就可以了。進入patch內部
patch函數主要接收oldVnode 與 vnode兩個參數,其實就是新舊兩棵虛擬樹。這里經過判斷條件 !isRealElement && sameVnode(oldVnode, vnode),不是真實節點 且是相同的vnode,進入patchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly); 我們只要關注oldVnode, vnode這兩個參數即可。
按照我們的例子,此時的oldVnode 與 vnode分別是
此處只列出關鍵屬性tag, key, elm, children,elm,還有很多其他的屬性沒有列出。真實的虛擬樹節點應該是如下圖
我們能看出 兩個vnode之間就是children[0]的不同:
追蹤流程發現,我們進入oldVnode 與 vnode的children進行對比,在updateChildren函數中。
我們先不去看updateChildren的邏輯,繼續看patchVnode這個函數其他的邏輯分支,得出 oldVnode 與 vnode的對比流程 :
總結: patchVnode這個方法的主要作用是對比兩個虛擬節點過程中去更新真實dom
接下來我們進入updateChildren流程,這是兩個children的對比,看一下這個函數的定義
函數解讀:
下面是兩個數組進行diff的流程,也就是diff演算法
diff解讀:
新舊兩個數組,都有雙端指針,兩端指針向中間靠攏,直到某個數組的兩端指針相交則退出循環。
在這個過程中,會先判斷是否有以下四種情況
如果不符合這4種情況,那就基於舊數組遍歷一次,拿到每個節點的key和index,就是oldKeyToIdx: {key1: 0, key2: 1}這種情況。然後去新數組首個節點開始匹配,匹配到就進行遞歸patchVnode流程,沒匹配到就進行創建新節點,插入到真實dom節點裡面去。
當循環結束,此時要麼是舊數組相交,要麼是新數組相交,只有這兩種情況:
至此diff流程結束。
兩個虛擬樹進行對比:
patch(oldVnode, vnode) -> patchVnode(oldVnode, vnode) -> updataChildren(oldCh, newCh)
在updataChildren(oldCh, newCh)的過程中也會進行 patchVnode(oldVnode, vnode) ,如此虛擬樹深度優先遞歸diff完成。
更加詳細直觀的圖看此鏈接
https://www.processon.com/view/5e809004e4b08e4e2447d02e
Ⅹ Diff演算法
Diff演算法的作用是用來計算出 Virtual DOM 中被改變的部分,然後針對該部分進行原生DOM操作,而不用重新渲染整個頁面。
Diff演算法有三大策略:
三種策略的執行順序也是順序依次執行。
Tree Diff 是對樹每一層進行遍歷,找出不同,如圖1所示。
Component Diff 是數據層面的差異比較
Element Diff 真實DOM渲染,結構差異的比較
首先進行第一層比較,第一層都是R,不發生變化;然後進入第二層Component Diff,發現A組件沒有,則刪除A及其子組件B、C;最後比較第三層,創建A及其子組件B、C。
當節點處於同一層級時,Diff提供三種DOM操作: 刪除 、 移動 、 插入 。
如圖2所示,首先將OldVnode 和 NewVnode的首尾位置分別標記為oldS、oldE、newS、newE。
(1) oldS和newS相同,不發生變化,oldS++,newS++。
(2) newS與OldVnode不匹配,oldS前面插入f,newS++。
(3) newS與oldE相同,oldE移動到oldS前面,newS++,oldE--。
(4) newE與oldE相同,不發生變化,newE--,oldE--。
(5) 都不相同,oldS前插入newE,刪除oldS,oldS++,newS++,newE--,oldE--。
(6) oldS > oldE,Diff結束,最後結果為:a、f、d、e、c。
最後附上核心源碼分析:
patch
這個函數做了以下事情:
updateChildren
上一篇 虛擬DOM : https://www.jianshu.com/p/580157c93c53