vue箭頭函數this作用域

在做vue項目時用到了axios,但是發現axios請求之後的回調函數裏this並不指向當前vue實例,從而導致瀏覽器報錯。

出錯代碼及結果:

 created : function(){
      axios.get('static/data.json').then(function(res){
          console.log(this)    //undefined
      this.user = res.data.user
   })
  }

(報錯截圖)
在這裏插入圖片描述

普通函數代碼改版(正確):

 created : function(){
      var _this = this
      axios.get('static/data.json').then(function(res){
          console.log(this)    //undefined
          console.log(_this)   //VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
      _this.user = res.data.user
   })
  }

從以上結果來看,在created下的函數this指向的是當前創建的vue實例,而在這些函數內部使用例如axios與後臺交互後回調函數的內部的this並非指向當前的vue實例;
若想拿到後臺回傳的數據更新data裏的數據,不能在回調函數中直接使用this,而要用在外部函數定義的變量存儲的this,也就是當前vue的實例。
箭頭函數代碼改版(正確):

created : function(){
      axios.get('static/data.json').then((res) => {
          console.log(this)      //VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
      this.user = res.data.user
   })
  }

箭頭函數相當於匿名函數,並且簡化了函數定義。看上去是匿名函數的一種簡寫,但實際上,箭頭函數和匿名函數有個明顯的區別:箭頭函數內部的this是詞法作用域,由上下文確定。此時this在箭頭函數中已經按照詞法作用域綁定了。很明顯,使用箭頭函數之後,箭頭函數指向的函數內部的this已經綁定了外部的vue實例了.

<template>
  <div id="example">
    <button @click="decrement">-</button>
    {{count}}
    {{dataCount}}
    <button @click="increment">+</button>
    <div>{{sex}}</div>
    <div>{{from}}</div>
    <div>{{myCmpted}}</div>
  </div>
</template>
<script>
import { mapState } from 'vuex'
export default {
  data () {
    return {
      str: '國籍',
      dataCount: this.$store.state.count
    }
  },
  computed: mapState({
    count: 'count', // 第一種寫法
    sex: (state) => state.sex, // 第二種寫法
    from: function (state) { // 用普通函數this指向vue實例,要注意
      return this.str + ':' + state.from
    },
    // 注意下面的寫法看起來和上面相同,事實上箭頭函數的this指針並沒有指向vue實例,因此不要濫用箭頭函數
    // from: (state) => this.str + ':' + state.from
    myCmpted: function () {
      // 這裏不需要state,測試一下computed的原有用法
      return '測試' + this.str
    }
  }),
  methods: {
    increment () {
      this.$store.commit('increment')
    },
    decrement () {
      this.$store.commit('decrement')
    }
  },
  created () {
    // 寫個定時器,發現computed依舊保持了只要內部有相關屬性發生改變不管是當前實例data中的改變,還是vuex中的值改變都會觸發dom和值更新
    setTimeout(() => {
      this.str = '國家'
    }, 1000)
  }
}
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章