Vue生命週期的理解

奮鬥路上的小菜雞發表於2018-06-07

image

測試程式碼:

    <div id="app">
        <h2>{{ msg }}</h2>
        <button @click="init" type="button">點選</button>
    </div>
    <script>
     var vm =  new Vue({
        el: '#app',
        data: {
          msg: "hello word!"
        },
        methods: {
          init () {
            alert('init');
          }

        },
        beforeCreate () {
          console.log('======beforeCreate=====');
          console.log(`el: ${this.$el}`);
          console.log(`data: ${this.$data}`);
          console.log(`init: ${this.init}`);
        },
        created () {
          console.log('======created=====');
          console.log(`el: ${this.$el}`);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
          // this.$data.msg = '1111'; // 這是可以對資料進行更改,但是不會觸發update生名周期函式,所以一般會在這裡做資料請求
        },
        beforeMount (){
          console.log('======beforeMount=====');
          console.log(`el: ${this.$el}`);
          console.log(this.$el);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
          // 這裡不做任何事,同時也不能修改資料
        },
        mounted () {
          console.log('======mounted=====');
          console.log(`el: ${this.$el}`);
          console.log(this.$el);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
        },
        beforeUpdate () {
          console.log('======beforeUpdateupdated=====');
          console.log(`el: ${this.$el.innerHTML}}`);
          console.log(this.$el);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
        },
        updated () {
          console.log('======updated=====');
          console.log(`el: ${this.$el.innerHTML}`);
          console.log(this.$el);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
          console.log(`init: ${this.init}`);
        },
        beforeDestroy () {
          console.log('======beforeDestroy=====');
          console.log(`el: ${this.$el}`);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
        },
        destroyed () {
          console.log('======destroyed=====');
          console.log(`el: ${this.$el}`);
          console.log(`data: ${this.$data}`);
          console.log(`message: ${this.msg}`);
        }
      })
      // vm.$mount(app);
    </script>

複製程式碼
  • beforCreate 和 created之間

    • 檢測data資料的變化,初始化事件。
    • 這時候並沒有el
  • created

    • 沒有el, Dom 沒有生成
  • created 和 beforMount之間

    • 首先判斷是否有el選項,如果沒有暫時停止生命週期,直到手動執行vm.mount(el),有則繼續編譯過程,繼續執行
    • 在判斷是否有template選項,如果沒有采用外部html模版,否則採用template選項編譯成render函式
    • 這裡的render 指的是jsx寫法。
    • 優先順序 render > template > 外部的html
    • 在created時,是可以修改資料的,通常我們會在這裡向伺服器請求資料
  • ==問題==:為什麼需要去判斷el 和 template 選項呢?

  • ==結論==:首先我們需要el選擇器,否則生命週期會暫時被終止,到created就停止了,所以el選擇器為前提條件,必須在template之前,通過對應的el選擇器拿到相對應的template。對於template優先順序的問題,template編輯後都要轉換成render函式,更接近Vue解析器,接著就是vue例項中的template選項了,如果template和外部的html同時存在,那麼template優先順序高於外部的html

  • beforMount

    • el、 data初始化,拿到了虛擬dom (virtual dom)這時的資料還未進行渲染,{{message}} 只是一個佔位符。
  • Mounted

    • 渲染真實的Dom(適合操作dom)
  • beforeUpdate

    • 此時,元素的真實dom內容還未改變
  • Updated

    • 重新渲染虛擬 dom,並通過 diff 演算法對比 vnode 節點差異更新真實 dom
  • beforeDestroy

  • destroyed

    • 例項銷燬後雖然 dom 和屬性方法都還存在,但改變他們都將不再生效!

相關文章