第三趴:vue框架進階

整理中高級前端系列,能夠看成面試複習,也能夠看成實戰來看,分享一下 方便本身,方便他人。有不足的地方歡迎評論~css

第一趴:css進階前端

第二趴:js進階vue

第三趴:vue框架進階node

第四趴:工程化react

MVC架構 (model、controller、view)

  • View: 檢測用戶輸入、操做(鍵盤、鼠標)行爲,傳遞調用Controller執行對應邏輯。View更新須要從新獲取 Model的數據。
  • Controller:是View和Model 之間協做的應用層,負責業務邏輯處理。
  • Model:數據層,數據變化後 經過觀察者模式通知 View更新視圖。

優勢:面試

  • 模塊化:低耦合、可替換、可擴展性、可複用性強
  • 多視圖更新:使用觀察者模式能夠作到 單方Model通知多視圖 實現數據更新

缺點:算法

  • 依賴強:View和 Model 強依賴,很難抽離成 組件化

MVVM框架核心原理

圖上能夠看到,view經過viewmodel 的DOM Listeners 將事件綁定到 Model上,而Model則經過 Data Bindings來管理View中的數據,View-Model從中起到一個鏈接橋的做用。

更詳細的查看 vuex

雙向數據綁定(響應式)原理

vue.js 是採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調。segmentfault

Vue實現這種數據雙向綁定的效果,須要三大模塊:數組

  • Observer:可以對數據對象的全部屬性進行監聽,若有變更可拿到最新值並通知訂閱者
  • Compile:對每一個元素節點的指令進行掃描和解析,根據指令模板替換數據,以及綁定相應的更新函數
  • Watcher:做爲鏈接Observer和Compile的橋樑,可以訂閱並收到每一個屬性變更的通知,執行指令綁定的相應回調函數,從而更新視圖

Vue全家桶

組件深刻( 組件通訊、生命週期 )

  • 使用 kebab-case my-component-name 或者 MyComponentName

組件通訊:

  1. 父子之間:props ----- $emit
  2. this.parent.event 調用父組件的方法、this.refs.xxx.屬性/方法:父組件裏直接獲取子組件 方法和屬性
  3. eventBus模式:新建Vue事件bus對象,而後經過 bus.emit 觸發事件,bus.on監聽觸發事件。

腳手架的 使用

Vue Loader

這個插件是必須的! 將你定義過的其餘規則賦址並應用到 .vue文件裏相應語言的塊。例如:你有一條匹配/\.js$/ 的規則,那麼它會應用到 .vue文件裏的 <script>

路由 原理

HashHistory:利用URL中的 hash("#")

  • hash是用來指導瀏覽器動做的,對服務器端徹底無用,所以 改變hash不會從新加載頁面。
  • 能夠爲 hash 的改變添加監聽事件:

window.addEventListener("hashchange", funcRef, false)

  • 每次改變hash(window.location.hash)都會在瀏覽器的訪問歷史中增長一個記錄

利用這幾點特性,就能夠實現前端路由 【更新視圖但不從新請求頁面】的功能了

HashHistory.push()

從設置路由改變到視圖更新的流程以下: $router.push() --> HashHistory.push() --> History.transitionTo() --> History.updateRoute() --> {app._route = route} --> vm.render()

HashHistory.replace()

其實和push()相似,不一樣就是 替換掉當前路由,調用的是window.location.replace方法。

HTML5History:

利用HTML5中新增的方法pushState\replaceState

  • pushState() 、replaceState()使得咱們能夠對瀏覽器歷史記錄棧進行修改
window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
複製代碼

實現原理:代碼結構以及更新視圖的邏輯與hash模式基本相似,只不過將對window.location.hash直接進行賦值window.location.replace(),改成了調用history.pushState()和history.replaceState()方法。

非瀏覽器環境準備了一個abstract模式 (沒使用過 可百度)

vuex 原理

state: 存儲數據(至關於 data)

咱們設置在state中的屬性會被存儲在根元素中, this._modules = new ModuleCollection(options) //初始化

const state = this._modules.root.state // 獲取定義的state

vuex初始化時先去獲取定義在state屬性的值 new ModuleCollection(options) 進行模塊收集(從新組裝 store中的相關屬性),最終造成一顆module樹。

getter:獲取store屬性方法 (至關於 computed)

mutations: 更改store中狀態的惟一方法就是 提交 mutation,相似於調用事件(methods)

視圖經過點擊事件,觸發 mutattions中的方法,能夠更改state中的數據,此時 getters把數據反映到視圖。

action: 提交 mutation 去變動狀態

那麼action 能夠理解是 爲了處理異步,單純多加的一層。

dispatch、commit

在vue中 咱們觸發 click事件,就能觸發 methods中的方法。可是 vuex就不行,必定要有個東西來觸發才行,就至關於自定義事件on\emit。

關係就是,經過dispatch來觸發actions中得方法,action中commi去觸發mutions中方法。

Proxy與Object.defineProperty的優劣對比?

Proxy的優點:

  • 能夠直接監聽對象而非屬性
  • 能夠直接監聽數組的變化
  • Proxy返回的是一個新對象,咱們能夠只操做新的對象達到目的,而Object.defineProperty只能遍歷對象屬性直接修改
  • 做爲新標準會收到瀏覽器廠商重點持續的性能優化。

Object.defineProperty的優點以下:

虛擬dom原理

Virtual DOM是對DOM的抽象,本質上是JavaScript對象,這個對象就是更加輕量級的對DOM的描述.

出發點

Virtual DOM最初的目的,就是更好的跨平臺,好比Node.js就沒有DOM,若是想實現SSR(服務端渲染),那麼一個方式就是藉助Virtual DOM,由於Virtual DOM自己是JavaScript對象.

主流

現代前端框架的一個基本要求就是無須手動操做DOM, 一方面是由於手動操做DOM沒法保證程序性能,多人協做的項目中若是review不嚴格,可能會有開發者寫出性能較低的代碼, 另外一方面更重要的是省略手動DOM操做能夠大大提升開發效率.

實現流程

一、須要一個**函數建立單個Virtual DOM **,這個函數很簡單,接受必定的參數,再根據這些參數返回一個對象,這個對象就是DOM的抽象.

/**
 * 生成 vnode
 * @param  {String} type     類型,如 'div'
 * @param  {String} key      key vnode的惟一id
 * @param  {Object} data     data,包括屬性,事件等等
 * @param  {Array} children  子 vnode
 * @param  {String} text     文本
 * @param  {Element} elm     對應的 dom
 * @return {Object}          vnode
 */
function vnode(type, key, data, children, text, elm) {
  const element = {
    __type: VNODE_TYPE,
    type, key, data, children, text, elm
  }
  return element
}
複製代碼

二、DOM實際上是一個Tree,咱們接下來要作的就是聲明一個函數用於建立DOM Tree的抽象 -- Virtual DOM Tree.

三、Virtual DOM 歸根究竟是JavaScript對象,咱們得想辦法將Virtual DOM與真實的DOM對應起來,也就是說,須要咱們聲明一個函數,此函數能夠將vnode轉化爲真實DOM.

四、Virtual DOM 的 diff纔是整個Virtual DOM 中最難理解也最核心的部分,diff的目的就是比較新舊Virtual DOM Tree找出差別並更新.

Virtual DOM的優化

snabbdom.js已是社區內主流的Virtual DOM實現了**,vue 2.0階段與snabbdom.js同樣**都採用了上面講解的 「雙端比較算法」,那麼有沒有一些優化方案可使其更快?

其實,社區內有更快的算法,例如inferno.js就號稱最快react-like框架(雖然inferno.js性能強悍的緣由不只僅是算法,可是其diff算法的確是目前最快的),而vue 3.0就會借鑑inferno.js的算法進行優化.

Vue中的key到底有什麼用?

diff算法的過程當中,先會進行新舊節點的首尾交叉對比,當沒法匹配的時候會用新節點的key與舊節點進行比對,而後超出差別.

快速: key的惟一性能夠被Map數據結構充分利用,相比於遍歷查找的時間複雜度O(n),Map的時間複雜度僅僅爲O(1).

$nextTick的原理

將回調延遲到下次DOM更新循環以後執行。在修改數據以後當即使用它,而後等待DOM更新。

<template>
	<div id="example">{{message}}</div>
</template>
<script>
    var vm = new Vue({
      el: '##example',
      data: {
        message: '123'
      }
    })
    vm.message = 'new message' // 更改數據
    console.log(vm.$el.innerHTML) // '123'
    Vue.nextTick(function () {
      console.log(vm.$el.innerHTML) // 'new message'
    })
</script>
複製代碼

在上面這個例子中,當咱們經過vm.message = 'new message'更新數據時,此時該組件不會當即從新渲染。當刷新事件隊列時,組件會在下一個事件循環「tick」中從新渲染。因此當咱們更新完數據後,此時又想基於更新後的DOM狀態來作點什麼,此時咱們就須要使用Vue.nextTick(callback),把基於更新後的DOM狀態所須要的操做放入回調函數callback中,這樣回調函數將在DOM更新完成後被調用。

數據爲何頻繁變化但只會更新一次

vue異步執行DOM更新

首屏加載性能優化

此點其實在說的是 白屏問題,白屏時間就是 當用戶地址欄按下確認鍵開始到首次內容繪製(即看到第一個內容)。 因此 解決 白屏問題 纔是關鍵 優化點。 ** 咱們先梳理下白屏時間內發生了什麼:

  1. 回車按下,瀏覽器解析網址,進行 DNS 查詢,查詢返回 IP,經過 IP 發出 HTTP(S) 請求
  2. 服務器返回HTML,瀏覽器開始解析 HTML,此時觸發請求 js 和 css 資源
  3. js 被加載,開始執行 js,調用各類函數建立 DOM 並渲染到根節點,直到第一個可見元素產生

開啓 HTTP2

  1. http2 的通訊效率更高
  2. 能夠進行多路複用
  3. http2 能夠頭部壓縮,可以節省消息頭佔用的網絡的流量

使用骨架屏

第一趴:css進階

第二趴:js進階

第三趴:vue框架進階

第四趴:工程化

同窗以爲有幫助的能夠點個贊哈,以示鼓勵 😊

相關文章
相關標籤/搜索