對vue生命週期/鉤子函數的理解

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

全部的生命週期鉤子自動綁定this上下文到實例中,所以你能夠訪問數據,對屬性和方法進行運算。這意味着你不能使用箭頭函數來定義一個生命週期方法(例如created: () => this.fetchTodos())。這是由於箭頭函數綁定了父上下文,所以this與你期待的 Vue 實例不一樣,this.fetchTodos的行爲未定義。html

下面附加一張生命週期圖示vue

 

 

 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中的事件都不能得到到;java

    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"節點進行操做;vue-router

    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 函數首次被調用。api

  4. mounted
    官方說明:el 被新建立的 vm.$el 替換,並掛載到實例上去以後調用該鉤子。若是root實例掛載了一個文檔內元素,當 mounted 被調用時 vm.$el 也在文檔內。
    解釋說明:掛載完畢,這時dom節點被渲染到文檔內,一些須要dom的操做在此時才能正常進行app

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

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

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在請求成功以前執行,那將很遺憾——默認選項會設置失敗ide

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();
    });
  });

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

相關文章
相關標籤/搜索