1. 程式人生 > 其它 >個人自學前端28-Vue5-虛擬節點,生命週期

個人自學前端28-Vue5-虛擬節點,生命週期

目錄

一. 虛擬節點

目前流行的檢視框架都是基於虛擬節點技術開發的.
檢視框架 => 更新檢視的最後非同步是DOM操作. => 儘量以最低的代價進行DOM操作.
檢視框架如何進行最低代價的DOM操作 => 虛擬節點 => 虛擬節點的更新 => diff演算法.
虛擬節點 => 一個純物件 => 描述真實節點.
虛擬節點在描述一個標籤時,都有3個最基本的屬性 => 標籤名,屬性列表,子節點列表。
虛擬節點就是真實節點的js描述.(AST語法樹)

    const Vnode = {
      // 描述標籤名
      tag: 'div',
      // 描述屬性節點列表
      attrs: [{id: 'app'}],
      children: [{
        tag: 'h3',
        attrs: [],
        children: ['Vue你好']
      }]
    }
    console.log(vm._vnode);

真實節點更新 => 一定是DOM操作完成.
虛擬節點更新 => 修改純物件.

如何根據更新後的虛擬節點,決定如何進行DOM操作去更新真實節點. => diff演算法.
diff演算法 => 比較更新前和更新後的虛擬節點一桶,最終決定如何進行DOM操作.

二. 生命週期

Vue的生命週期 => Vue例項從建立達到銷燬過程中的特定階段.

new Vue例項化(元件例項化)
觸發beforeCreate
通過Object.defineProperty給data資料設定資料劫持
觸發created.
判斷有沒有el選項.
如果沒有el選項,則等待$mount方法觸發,如果這個方法也沒觸發,則例項化失敗.( $mount(選擇器) === el: 選擇器)
如果有,繼續判斷有沒有template選項
如果有template選項,則編譯template
如果沒有template選項,則編譯el所在的標籤
觸發beforeMount
根據編譯的虛擬節點生成真實節點vm.$el.並且用真實的新檢視替換掉老檢視
觸發mounted.進入執行階段.
監控資料變化,觸發beforeUpdate,updated
例項(元件DOM)銷燬時,先呼叫beforeDestory
呼叫Destroyed,全部銷燬

1. 建立期

建立 => 給vue例項新增資料 => 給data設定資料劫持.
建立前後 => 資料劫持前後.(Object.defineProperty進行資料劫持前後)
這兩個鉤子只會觸發一次.

  • beforeCreate
    建立前 => 沒什麼用
  • created
    建立後 => 一般用於資料初始化。
    在這個建構函式內只能操作資料,不能操作檢視.

2. 掛載期

掛載 => 新檢視替換老檢視.(元件template替換元件標籤).
掛載前後 => 新檢視出現前後.
這兩個鉤子也只觸發一次.
mounted => 檢視初始化.
掛載都發生了什麼事情?

  1. 編譯template.(把字串模板編譯成虛擬節點).
  2. 編譯遇到指令和插值表示式,都會進行求值.(收集依賴).
  3. 把虛擬節點轉換為新檢視,替換老檢視.

3. 更新期

檢視更新前後 => 分別觸發beforeUpdate和updated
預設不觸發(Vue例項化階段不觸發).
Vue例項化完成之後,檢視再更新,才會觸發.
有可能觸發很多次.

  1. updated和watch的區別
    updated => 檢視更新就觸發.不能知道本次更新是由於哪個資料變化導致的.具有響應式效果的資料變化,都觸發updated.
    watch => 資料變化就觸發.監聽哪個資料,就觸發哪個方法.
  2. 更新真實節點
    資料變化 => 導致檢視更新 (響應式)
    資料變化 => 先更新虛擬節點 => diff演算法判斷 => 最後更新真實節點。
    1. 原地更新.(標籤不增刪,不移動,直接修改內容或者屬性)(更新前後是同一個標籤) => 更新前後的tag和key完全一致.
    2. 替換更新.(會增刪,移動元素)(新增,刪除,移動) => tag或key有一個不一樣.
  3. 什麼時候原地更新?什麼時候替換更新?
    1. 比較更新前後的虛擬節點.(同級比較)
    2. 如果同級的tag一致,並且key一樣,則表示更新前後是同一個標籤,使用原地更新策略.
    3. 如果同級的tag或者key有一個不一樣,則表示更新前後不是同一個標籤,使用替換更新策略.

4. 銷燬期

destroyed => 元件銷燬後的善後處理,例如停止定時器
元件銷燬只是讓資料不驅動檢視更新了而已.元件例項還是存在的.

5.父子元件生命週期順序

父beforeCreate
父created
父beforeMount
子beforeCreate
子created
子beforeMount
子mounted
父mounted

為什麼順序是這樣的. => 函式執行順序回答.父元件的檢視編譯就是一個函式從上往下執行.
能不能修改這個順序.(4父4子) => 通過v-if實現.父元件掛載後再編譯子元件.

三. nextTick

如何針對某個資料變化導致的檢視更新寫單獨的邏輯?
vue的檢視更新是非同步的,資料變化不會馬上導致檢視更新.

nextTick的回撥函式,會在檢視更新後自動觸發.只觸發一次
一定是用來處理跟檢視相關的邏輯.

    const App = {
      template: `
        <div>
          <button @click='fn'>修改str</button>
          <ul ref='ul'>
            <li v-for='d in count'>{{d}}</li>
          </ul>
        </div>
      `,
      data() {
        return {
          count: 0
        }
      },
      methods: {
        fn() {
          // 資料變化會導致檢視變化.檢視變化完成之後,就會觸發nextTick
          this.count++;
          // 這裡只會在count變化導致的檢視更新後觸發.
          this.$nextTick(() => {
            let oUl = this.$refs.ul;
            oUl.scrollTop = oUl.scrollHeight - oUl.clientHeight;
          });
        }
      }
    }