Vue-06-生命周期-箭頭函數(shù)

今天,我們來(lái)了解一下生命周期的運(yùn)行結(jié)構(gòu);它的核心部分就是mounted,下面就是它的圖解:
[圖片上傳中...(360截圖20181001105915688.jpg-d881fe-1538362800251-0)]
360截圖20181001105915688.jpg

Vue提供的可以注冊(cè)的鉤子都在上圖片的紅色框標(biāo)注。 他們是:

beforeCreate
在實(shí)例初始化之后,數(shù)據(jù)觀測(cè)(data observer) 和 event/watcher 事件配置之前被調(diào)用。

created
實(shí)例已經(jīng)創(chuàng)建完成之后被調(diào)用。在這一步,實(shí)例已完成以下的配置:數(shù)據(jù)觀測(cè)(data observer),屬性和方法的運(yùn)算, watch/event 事件回調(diào)。然而,掛載階段還沒(méi)開始,$el 屬性目前不可見。

beforeMount
在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用。

mounted
el 被新創(chuàng)建的 vm.el 替換,并掛載到實(shí)例上去之后調(diào)用該鉤子。如果 root 實(shí)例掛載了一個(gè)文檔內(nèi)元素,當(dāng) mounted 被調(diào)用時(shí) vm.el 也在文檔內(nèi)。

beforeUpdate
數(shù)據(jù)更新時(shí)調(diào)用,發(fā)生在虛擬 DOM 重新渲染和打補(bǔ)丁之前。 你可以在這個(gè)鉤子中進(jìn)一步地更改狀態(tài),這不會(huì)觸發(fā)附加的重渲染過(guò)程。

updated
由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補(bǔ)丁,在這之后會(huì)調(diào)用該鉤子。

當(dāng)這個(gè)鉤子被調(diào)用時(shí),組件 DOM 已經(jīng)更新,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作。然而在大多數(shù)情況下,你應(yīng)該避免在此期間更改狀態(tài),因?yàn)檫@可能會(huì)導(dǎo)致更新無(wú)限循環(huán)。

該鉤子在服務(wù)器端渲染期間不被調(diào)用。

beforeDestroy
實(shí)例銷毀之前調(diào)用。在這一步,實(shí)例仍然完全可用。

destroyed

Vue 實(shí)例銷毀后調(diào)用。調(diào)用后,Vue 實(shí)例指示的所有東西都會(huì)解綁定,所有的事件監(jiān)聽器會(huì)被移除,所有的子實(shí)例也會(huì)被銷毀。 該鉤子在服務(wù)器端渲染期間不被調(diào)用。

接下來(lái)我們做一個(gè)例子,看一下Vue中所有的生命周期怎么用的。


<!DOCTYPE html> 
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue入門之生命周期</title>
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <p>{{ number }}</p>
    <input type="text" name="btnSetNumber" v-model="number">
  </div>
  <script>
    var app = new Vue({         
      el: '#app',               
      data: {                   
        number: 1
      },
      beforeCreate: function () {
        console.log('beforeCreate 鉤子執(zhí)行...');
        console.log(this.number)
      },
      cteated: function () {
        console.log('cteated 鉤子執(zhí)行...');
        console.log(this.number)
      },
      beforeMount: function () {
        console.log('beforeMount 鉤子執(zhí)行...');
        console.log(this.number)
      },
      mounted: function () {
        console.log('mounted 鉤子執(zhí)行...');
        console.log(this.number)
      },
      beforeUpdate: function () {
        console.log('beforeUpdate 鉤子執(zhí)行...');
        console.log(this.number)
      },
      updated: function () {
        console.log('updated 鉤子執(zhí)行...');
        console.log(this.number)
      },
      beforeDestroy: function () {
        console.log('beforeDestroy 鉤子執(zhí)行...');
        console.log(this.number)
      },
      destroyed: function () {
        console.log('destroyed 鉤子執(zhí)行...');
        console.log(this.number)
      },
    });
  </script>
</body>
</html>
再看一個(gè)綜合的實(shí)戰(zhàn)的例子,可能涉及到ajax和組件,不過(guò)先看一下vue的生命周期的例子的用法:

import Axios from 'axios'       // 這是一個(gè)輕量級(jí)的ajax庫(kù),import是es6模塊導(dǎo)入的語(yǔ)法。
export default {                // 這是一個(gè)vue的模塊,后面講奧。
  name: 'app',
  components: {
  },
  data: function () {
    return {
      list: []
    }
  },
  mounted: function () {          // 掛在完成后的生命周期鉤子注冊(cè)。
    this.$nextTick(function () {  // 等待下一次更新完成后執(zhí)行業(yè)務(wù)處理代碼。
      Axios.get('/api/menulist', {// 將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行。在修改數(shù)據(jù)之后立即使用它,然后等待 DOM 更新
        params: {
        }
      }).then(function (res) {
        this.list = res.data
      }.bind(this))
    })
  }
}
B.箭頭函數(shù):

前言

this 指向問(wèn)題是入坑前端必須了解知識(shí)點(diǎn),現(xiàn)在迎來(lái)了ES6時(shí)代,因?yàn)榧^函數(shù)的出現(xiàn),所以感覺(jué)有必要對(duì) this 問(wèn)題梳理一下,遂有此文

在非箭頭函數(shù)下, this 指向調(diào)用其所在函數(shù)的對(duì)象,而且是離誰(shuí)近就是指向誰(shuí)(此對(duì)于常規(guī)對(duì)象,原型鏈, getter & setter等都適用);構(gòu)造函數(shù)下,this與被創(chuàng)建的新對(duì)象綁定;DOM事件,this指向觸發(fā)事件的元素;內(nèi)聯(lián)事件分兩種情況,bind綁定, call & apply 方法等, 容以下一步一步討論。箭頭函數(shù)也會(huì)穿插其中進(jìn)行討論。

全局環(huán)境下

在全局環(huán)境下,this 始終指向全局對(duì)象(window), 無(wú)論是否嚴(yán)格模式;

console.log(this.document === document); // true

// 在瀏覽器中,全局對(duì)象為 window 對(duì)象:
console.log(this === window); // true

this.a = 37;
console.log(window.a); // 37

函數(shù)上下文調(diào)用

函數(shù)直接調(diào)用

普通函數(shù)內(nèi)部的this分兩種情況,嚴(yán)格模式和非嚴(yán)格模式。

非嚴(yán)格模式下,this 默認(rèn)指向全局對(duì)象window

function f1(){
  return this;
}

f1() === window; // true

而嚴(yán)格模式下, this為undefined

function f2(){
  "use strict"; // 這里是嚴(yán)格模式
  return this;
}

f2() === undefined; // true

對(duì)象中的this

對(duì)象內(nèi)部方法的this指向調(diào)用這些方法的對(duì)象,

  1. 函數(shù)的定義位置不影響其this指向,this指向只和調(diào)用函數(shù)的對(duì)象有關(guān)。
  2. 多層嵌套的對(duì)象,內(nèi)部方法的this指向離被調(diào)用函數(shù)最近的對(duì)象(window也是對(duì)象,其內(nèi)部對(duì)象調(diào)用方法的this指向內(nèi)部對(duì)象, 而非window)。
//1
var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};
console.log(o.f());  //37
var a = o.f;
console.log(a()):  //undefined

var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37

//2
o.b = {
  g: independent,
  prop: 42
};
console.log(o.b.g()); // logs 42

原型鏈中this

原型鏈中的方法的this仍然指向調(diào)用它的對(duì)象,與以上討論一致;看個(gè)例子,

var o = {
  f : function(){ 
    return this.a + this.b; 
  }
};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5

可以看出, 在p中沒(méi)有屬性f,當(dāng)執(zhí)行p.f()時(shí),會(huì)查找p的原型鏈,找到 f 函數(shù)并執(zhí)行,但這與函數(shù)內(nèi)部this指向?qū)ο?p 沒(méi)有任何關(guān)系,只需記住誰(shuí)調(diào)用指向誰(shuí)。

以上對(duì)于函數(shù)作為getter & setter 調(diào)用時(shí)同樣適用。

構(gòu)造函數(shù)中this

構(gòu)造函數(shù)中的this與被創(chuàng)建的新對(duì)象綁定。

注意:當(dāng)構(gòu)造器返回的默認(rèn)值是一個(gè)this引用的對(duì)象時(shí),可以手動(dòng)設(shè)置返回其他的對(duì)象,如果返回值不是一個(gè)對(duì)象,返回this。

function C(){
  this.a = 37;
}

var o = new C();
console.log(o.a); // logs 37

function C2(){
  this.a = 37;
  return {a:38};
}

var b = new C2();
console.log(b.a); // logs 38

以上兩個(gè)例子內(nèi)部的this都指向?qū)ο髈, 看到這里的你不妨在控制臺(tái)執(zhí)行下以上代碼,看看對(duì)象 o 和 b ,這些是屬于構(gòu)造函數(shù)的內(nèi)容了,此處不多做介紹。(C2函數(shù)中的this.a = 37 對(duì)整個(gè)過(guò)程完全沒(méi)有影響的, 可以被忽略的)。

call & apply

當(dāng)函數(shù)通過(guò)Function對(duì)象的原型中繼承的方法 call() 和 apply() 方法調(diào)用時(shí), 其函數(shù)內(nèi)部的this值可綁定到 call() & apply() 方法指定的第一個(gè)對(duì)象上, 如果第一個(gè)參數(shù)不是對(duì)象,JavaScript內(nèi)部會(huì)嘗試將其轉(zhuǎn)換成對(duì)象然后指向它。

例子:

function add(c, d){
  return this.a + this.b + c + d;
}

var o = {a:1, b:3};

add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

function tt() {
  console.log(this);
}
// 返回對(duì)象見下圖(圖1)
tt.call(5);  // Number {[[PrimitiveValue]]: 5} 
tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}
image

bind 方法

bind方法在ES5引入, 在Function的原型鏈上, Function.prototype.bind。通過(guò)bind方法綁定后, 函數(shù)將被永遠(yuǎn)綁定在其第一個(gè)參數(shù)對(duì)象上, 而無(wú)論其在什么情況下被調(diào)用。

function f(){
  return this.a;
}

var g = f.bind({a:"azerty"});
console.log(g()); // azerty

var o = {a:37, f:f, g:g};
console.log(o.f(), o.g()); // 37, azerty

DOM 事件處理函數(shù)中的 this & 內(nèi)聯(lián)事件中的 this

DOM事件處理函數(shù)

  1. 當(dāng)函數(shù)被當(dāng)做監(jiān)聽事件處理函數(shù)時(shí), 其 this 指向觸發(fā)該事件的元素 (針對(duì)于addEventListener事件)
  // 被調(diào)用時(shí),將關(guān)聯(lián)的元素變成藍(lán)色
    function bluify(e){
      //在控制臺(tái)打印出所點(diǎn)擊元素
      console.log(this);
      //阻止時(shí)間冒泡
      e.stopPropagation();
      //阻止元素的默認(rèn)事件
      e.preventDefault();      
      this.style.backgroundColor = '#A5D9F3';
    }

    // 獲取文檔中的所有元素的列表
    var elements = document.getElementsByTagName('*');

    // 將bluify作為元素的點(diǎn)擊監(jiān)聽函數(shù),當(dāng)元素被點(diǎn)擊時(shí),就會(huì)變成藍(lán)色
    for(var i=0 ; i<elements.length ; i++){
      elements[i].addEventListener('click', bluify, false);
    }

以上代碼建議在網(wǎng)頁(yè)中執(zhí)行以下,看下效果。

內(nèi)聯(lián)事件
內(nèi)聯(lián)事件中的this指向分兩種情況:

  1. 當(dāng)代碼被內(nèi)聯(lián)處理函數(shù)調(diào)用時(shí),它的this指向監(jiān)聽器所在的DOM元素
  2. 當(dāng)代碼被包括在函數(shù)內(nèi)部執(zhí)行時(shí),其this指向等同于 ****函數(shù)直接調(diào)用****的情況,即在非嚴(yán)格模式指向全局對(duì)象window, 在嚴(yán)格模式指向undefined
image

頁(yè)面的代碼塊

image

在瀏覽器內(nèi)顯示三個(gè)按鈕

image

依次點(diǎn)擊上邊的三個(gè)按鈕后在控制臺(tái)的輸出結(jié)果,

建議自己操作一遍以便于更好的理解。

setTimeout & setInterval

對(duì)于延時(shí)函數(shù)內(nèi)部的回調(diào)函數(shù)的this指向全局對(duì)象window(當(dāng)然我們可以通過(guò)bind方法改變其內(nèi)部函數(shù)的this指向)
看下邊代碼及截圖

//默認(rèn)情況下代碼
function Person() {  
    this.age = 0;  
    setTimeout(function() {
        console.log(this);
    }, 3000);
}

var p = new Person();//3秒后返回 window 對(duì)象
==============================================
//通過(guò)bind綁定
function Person() {  
    this.age = 0;  
    setTimeout((function() {
        console.log(this);
    }).bind(this), 3000);
}

var p = new Person();//3秒后返回構(gòu)造函數(shù)新生成的對(duì)象 Person{...}
image
image

箭頭函數(shù)中的 this

由于箭頭函數(shù)不綁定this, 它會(huì)捕獲其所在(即定義的位置)上下文的this值, 作為自己的this值,

  1. 所以 call() / apply() / bind() 方法對(duì)于箭頭函數(shù)來(lái)說(shuō)只是傳入?yún)?shù),對(duì)它的 this 毫無(wú)影響。
  2. 考慮到 this 是詞法層面上的,嚴(yán)格模式中與 this 相關(guān)的規(guī)則都將被忽略。(可以忽略是否在嚴(yán)格模式下的影響)

因?yàn)榧^函數(shù)可以捕獲其所在上下文的this值 所以

function Person() {  
    this.age = 0;  
    setInterval(() => {
        // 回調(diào)里面的 `this` 變量就指向了期望的那個(gè)對(duì)象了
        this.age++;
    }, 3000);
}

var p = new Person();

以上代碼可以得到我們所以希望的值,下圖可以看到,在setTimeout中的this指向了構(gòu)造函數(shù)新生成的對(duì)象,而普通函數(shù)指向了全局window對(duì)象

image
var adder = {
  base : 1,

  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function inFun(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1));         // 輸出 2
console.log(adder.addThruCall(1)); // 仍然輸出 2(而不是3,其內(nèi)部的this并沒(méi)有因?yàn)閏all() 而改變,其this值仍然為函數(shù)inFun的this值,指向?qū)ο骯dder

bind() & apply() 讀者可以自行測(cè)試

對(duì)于是否嚴(yán)格模式示例代碼(可以復(fù)制進(jìn)控制臺(tái)進(jìn)行驗(yàn)證)

var f = () => {'use strict'; return this};
var p = () => { return this};
console.log(1,f() === window);
console.log(2,f() === p());
//1 true
//2 true
image

以上的箭頭函數(shù)都是在方法內(nèi)部,總之都是以非方法的方式使用,如果將箭頭函數(shù)當(dāng)做一個(gè)方法使用會(huì)怎樣呢?
上例子

var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log( this.i, this)
  }
}
obj.b();  // undefined window{...}
obj.c();  // 10 Object {...}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 函數(shù)和對(duì)象 1、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門語(yǔ)言來(lái)說(shuō)都是核心的概念。通過(guò)函數(shù)可以封裝任意多條語(yǔ)句,而且...
    道無(wú)虛閱讀 4,950評(píng)論 0 5
  • 第3章 基本概念 3.1 語(yǔ)法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡(jiǎn)單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,514評(píng)論 0 21
  • 10.29 正在畫畫的我因?yàn)槟愕囊痪?,最近很冷漠,停下了畫筆, 糾結(jié)了很久,打下很多話又刪掉,最后只留下一個(gè)表情和...
    發(fā)清genius閱讀 424評(píng)論 0 0
  • 這樣的服飾很少見了,不知道是那個(gè)民族的... 我還真以為外國(guó)人什么也不怕呢... 李易峰:心中的男神,你這樣不好吧...
    朦朧月色閱讀 206評(píng)論 0 0

友情鏈接更多精彩內(nèi)容