對vue生命周期/鈎子函數的理解


對於實現頁面邏輯交互等效果,我們必須知曉vue的生命周期,才能愉快的玩耍,知道我們寫的東西應該掛載到哪里,vue官方給出的api講解的那叫一個簡單啊,如下:

所有的生命周期鈎子自動綁定this上下文到實例中,因此你可以訪問數據,對屬性和方法進行運算。這意味着你不能使用箭頭函數來定義一個生命周期方法(例如created: () => this.fetchTodos())。這是因為箭頭函數綁定了父上下文,因此this與你期待的 Vue 實例不同,this.fetchTodos的行為未定義。

下面附加一張生命周期圖示

 

 

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title></title>
 5     <meta charset="utf-8">
 6     <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
 7 </head>
 8 <body>
 9 
10 <div id="app">
11     <p>{{ message }}</p>
12 </div>
13 
14 <script type="text/javascript">
15     var app = new Vue({
16         el: '#app',
17         data: {
18             message: "this is a test"
19         },
20         beforeCreate: function () {
21             console.group('beforeCreate 創建前狀態===============》');
22             console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
23             console.log("%c%s", "color:red", "data   : " + this.$data); //undefined
24             console.log("%c%s", "color:red", "message: " + this.message)
25         },
26         created: function () {
27             console.group('created 創建完畢狀態===============》');
28             console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
29             console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
30             console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
31         },
32         beforeMount: function () {
33             console.group('beforeMount 掛載前狀態===============》');
34             console.log("%c%s", "color:red", "el     : " + (this.$el)); //已被初始化
35             console.log(this.$el);
36             console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
37             console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
38         },
39         mounted: function () {
40             console.group('mounted 掛載結束狀態===============》');
41             console.log("%c%s", "color:red", "el     : " + this.$el); //已被初始化
42             console.log(this.$el);
43             console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
44             console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
45         },
46         beforeUpdate: function () {
47             console.group('beforeUpdate 更新前狀態===============》');
48             console.log("%c%s", "color:red", "el     : " + this.$el);
49             console.log(this.$el);
50             console.log("%c%s", "color:red", "data   : " + this.$data);
51             console.log("%c%s", "color:red", "message: " + this.message);
52         },
53         updated: function () {
54             console.group('updated 更新完成狀態===============》');
55             console.log("%c%s", "color:red", "el     : " + this.$el);
56             console.log(this.$el);
57             console.log("%c%s", "color:red", "data   : " + this.$data);
58             console.log("%c%s", "color:red", "message: " + this.message);
59         },
60         beforeDestroy: function () {
61             console.group('beforeDestroy 銷毀前狀態===============》');
62             console.log("%c%s", "color:red", "el     : " + this.$el);
63             console.log(this.$el);
64             console.log("%c%s", "color:red", "data   : " + this.$data);
65             console.log("%c%s", "color:red", "message: " + this.message);
66         },
67         destroyed: function () {
68             console.group('destroyed 銷毀完成狀態===============》');
69             console.log("%c%s", "color:red", "el     : " + this.$el);
70             console.log(this.$el);
71             console.log("%c%s", "color:red", "data   : " + this.$data);
72             console.log("%c%s", "color:red", "message: " + this.message)
73         }
74     })
75 </script>
76 </body>
77 </html>
生命周期
  1. beforeCreate
  2. created
  3. beforeMount
  4. mounted
  5. beforeUpdate
  6. updated
  7. activated
  8. deactivated
  9. beforeDestroy
  10. destroyed

 

 

詳解:

  1. beforeCreate
    官方說明:在實例初始化之后,數據觀測(data observer) 和 event/watcher 事件配置之前被調用。
    解釋:這個時期,this變量還不能使用,在data下的數據,和methods下的方法,watcher中的事件都不能獲得到;

     beforeCreate() {
       console.log(this.page); // undefined
       console.log{this.showPage); // undefined
     },
     data() {
       return {
         page: 123
       }
     },
     methods: {
       showPage() {
         console.log(this.page);
       }
     }
    
  2. created
    官方說明:實例已經創建完成之后被調用。在這一步,實例已完成以下的配置:數據觀測(data observer),屬性和方法的運算, watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見。
    解釋說明: 這個時候可以操作vue實例中的數據和各種方法,但是還不能對"dom"節點進行操作;

     created() {
       console.log(this.page); // 123
       console.log{this.showPage); // ...
       $('select').select2(); // jQuery插件需要操作相關dom,不會起作用
     },
     data() {
       return {
         page: 123
       }
     },
     methods: {
       showPage() {
         console.log(this.page);
       }
     }
    
  3. beforeMounte
    官方說明:在掛載開始之前被調用:相關的 render 函數首次被調用。

  4. mounted
    官方說明:el 被新創建的 vm.$el 替換,並掛載到實例上去之后調用該鈎子。如果root實例掛載了一個文檔內元素,當 mounted 被調用時 vm.$el 也在文檔內。
    解釋說明:掛載完畢,這時dom節點被渲染到文檔內,一些需要dom的操作在此時才能正常進行

     mounted() {
       $('select').select2(); // jQuery插件可以正常使用
     },
    

這時初始化插件沒有問題,插件能正常運行,但是這並不代表萬事大吉;下面思考一個問題:

select2
select2

圖中的selectoption都是通過異步請求得到的,然后通過v-for渲染進去,到此一切看起來很正常。還有一個需求是當頁面刷新后要保留上次一查詢的條件。我通過vue-router來給select指定一個默認選項;

  <template v-for='(item, index) in agentList.name' >
     <option v-if='item == name' :key='index' selected :value="item">{{item}}</option>
      <option v-else :key='index' :value="item">{{item}}</option>
   </template>

那么問題就來了,option的獲得是一個異步請求,那這個請求完成的時刻和mounted的順序是什么?如果mounted在請求成功之前執行,那將很遺憾——默認選項會設置失敗

option有默認效果的是130,select中的值還是保持全部
option有默認效果的是130,select中的值還是保持全部

什么時候執行$('select').select2(),是解決這個問題的關鍵。大家肯定猜到了,mounted的確是在請求成功之前執行的,所以這時的辦法就是將$('select').select2()的執行放到請求成功的回調里執行:

  $.getJSON(urls.agentAndCity, {pageType: this.pageType}, (res) => {
    const a = this.agentList,
    d = res.data;
    a.id = d.orgIds;
    a.name = d.orgNames;
    a.city = d.cityMap;
    $('select').select2();
  });

本以為這樣就完美解決了,但是發現還是會出現和上圖一樣的效果;如何是好?這時輪到vm.$nextTick登場了:
說明: 將回調延遲到下次 DOM 更新循環之后執行。在修改數據之后立即使用它,然后等待 DOM 更新。
官方示例代碼:

    new Vue({
      // ...
      methods: {
      // ...
      example: function () {
      // 修改數據
      this.message = 'changed'
      // DOM 還沒有更新
        this.$nextTick(function () {
          // DOM 現在更新了
          // `this` 綁定到當前實例
          this.doSomethingElse()
        })
      }
    }
  })

所以我的解決辦法如下:

$.getJSON(urls.agentAndCity, {pageType: this.pageType}, (res) => {
    const a = this.agentList,
    d = res.data;
    a.id = d.orgIds;
    a.name = d.orgNames;
    a.city = d.cityMap;
    this.$nextTick(() => {
      $('select').select2();
    });
  });

至此這個問題才算比較滿意的解決

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM