簡體   English   中英

何時使用vm。或這個。在Vue.js

[英]When to Use vm. or this. in Vue.js

關於何時在vue.js中使用“this”這個詞,我有點困惑。 例如,在下面的代碼中我使用“vm”而不是“this”代碼不起作用。

我也看過一些使用“self”的例子,但我不是一個javascript大師,這真的讓人困惑。

var vm = new Vue({
        el: '#app',
        data: {
            tickets: [],
            top: 100,
            search: '',
            showAdd: false,
         },
        mounted: function () {
            this.$nextTick(function () {
                console.log('mounted');
                this.GetTickets(100);
            })
        },
        methods: {
            GetTickets: function (top) {
                axios.get('/api/Tickets', {
                    params: {
                        Top: top
                    }
                })
                    .then(function (response) {
                        vm.tickets = response.data;
                    })
                    .catch(function (error) {
                        console.log(error);
                    });
            },
            ClearTicket: function () {
                var t = {
                    "ticketSubject": '',
                    "contactName": '',
                    "createdAt": moment()
                }
                vm.ticket = t;
                vm.showAdd = !vm.showAdd;
            },
            AddTicket: function () {
                //vm.tickets.unshift(vm.ticket);
                axios.post('/api/Tickets', vm.ticket)
                    .then(function (response) {
                        console.log(response);
                        vm.GetTickets(100);
                    })
                    .catch(function (error) {
                        console.log(error);
                    });
                vm.showAdd = false;

            }
        },

    })

通常,在Vue中使用內部方法或計算屬性或生命周期處理程序,您將使用this來引用方法/計算/處理程序所附加的組件。 this指的是函數當前正在執行的上下文。

使用this時遇到麻煩的地方是在當前函數的上下文中聲明一個新函數時,就像你對一個promise( axios.postaxios.get )寫一個回調時發生的那樣。 考慮以下代碼:

AddTicket: function () {
  // "this", on this line, refers to the Vue
  // and you can safely use "this" to get any of the
  // data properties of the Vue
    axios.post('/api/Tickets', ...)
      .then(function (response) {
        // "this" HERE, does NOT refer to the Vue!!
        // The reason why explained below              
      })
}

在上面的代碼中,第一個注釋可以替換為使用this來獲取數據屬性或調用Vue( this.tickets )方法的this.tickets 然而,第二條評論是一個新的函數上下文中, this不會引用Vue。 這是因為在Javascript中使用function() {}語法聲明一個新函數時,該函數有自己的函數上下文,它與聲明它的函數不同

有幾種方法可以在Javascript中處理這個問題。 最常見的這些天,其一是使用閉包來捕捉正確的this ,或者用一個箭頭的功能。 考慮以下代碼:

AddTicket: function () {
  // As before, "this" here is the Vue
    axios.post('/api/Tickets', ...)
      .then((response) => {
        // "this" HERE is ALSO the Vue
      })
}

請注意,在此示例中,使用箭頭函數( () => {} )定義回調。 箭頭函數不會創建自己的函數上下文並使用聲明它們的上下文。 這也被稱為具有詞法范圍。

另一個最常見的解決方法是使用閉包。

AddTicket: function () {
  const self = this // Here we save a reference to the "this" we want
    axios.post('/api/Tickets', ...)
      .then(function(response){
        // and HERE, even though the context has changed, and we can't use
        // "this", we can use the reference we declared (self) which *is*
        // pointing to the Vue
        self.tickets = response
      })
}

最后,您可以使用綁定的方法來創建具有特定功能this ,雖然這並不常見,這幾天帶箭頭的功能可用。

AddTicket: function () {
    axios.post('/api/Tickets', ...)
      .then(function(response){
        this.tickets = response
      }.bind(this)) // NOTE the ".bind(this)" added to the end of the function here
}

在幾乎所有情況下,你真的應該在你的問題中做你做的事情,這是在變量vm保存對Vue的引用,並在Vue對象本身使用該變量。 這是一個不好的做法。

在任何情況下,如何使用正確的this一點在整個互聯網的許多帖子中都有詳細介紹, 這里也是StackOverflow

最后,這里是從修訂使得問題的代碼this 正確使用。

var vm = new Vue({
  el: '#app',
  data: {
    tickets: [],
    top: 100,
    search: '',
    showAdd: false,
    ticket: null
  },
  mounted: function () {
    // there is no need for $nextTick here
    this.GetTickets(100)
  },
  methods: {
    GetTickets: function (top) {
      axios.get('/api/Tickets', { params: { Top: top }})
        .then(response => this.tickets = response.data)
        .catch(error => console.log(error));
    },
    ClearTicket: function () {
      var t = {
        "ticketSubject": '',
        "contactName": '',
        "createdAt": moment()
      }
      this.ticket = t;
      this.showAdd = !this.showAdd;
    },
    AddTicket: function () {
      axios.post('/api/Tickets', this.ticket)
        .then(() => this.GetTickets(100))
        .catch(error => console.log(error));

      this.showAdd = false;
    }
  },
})

最后,很簡單。 在您不完全了解其工作原理之前,請遵循以下簡單規則:

使用this無處不在的Vue對象,外面使用它的參考標識符:

var vm = new Vue({
  // Use "this" inside
  el: '#app',
  data: {
    something: true
  },
  created: function () {
    this.something = false // like here
  }
})

// Here, outside, use reference iditentifier,
// as you have no other choice
vm.something = null

切勿在引用的對象本身內使用引用名稱。 在Vue對象之外,您沒有其他選擇,您只需使用引用名稱。

在Vue內部, this內容可能會有所不同。 還會。 它只是在每個函數/對象中自動創建的另一個對象。 所以你需要這個第二條規則:在你潛入嵌套的二級函數之前,將this保存到reference / variable。 為什么:

var vm = new Vue({
  el: '#app',
  data: {
    something: true
  },
  created: function () {
    // You are in first level function,
    // you can use "this"
    axios.get('/uri').then(function () {
      // Here you are in nested, second level
      // function. It will have own "this" object
      this.something = false // no error here but...
      // You did not changed "something" value in data object,
      // you just created new property also called "something",
      // but in this nested "this" object.
    })
  }
})

如上所述,每個函數都獲得它自己的this對象。 因此,使用'this.something = false',您只需在嵌套的二級函數中在'this'對象中創建新屬性'something',而不是在第一級函數中更改'this'。 換句話說,在嵌套函數,你失去了參考以往this從第一級的功能,因為它的內容與在嵌套函數創建的過程中新創建的內容overwrited。 因此,如果您需要在嵌套函數中使用this對象形成第一級函數,只需將其保存在另一個名稱下,該名稱將不會被覆蓋:

var vm = new Vue({
  el: '#app',
  data: {
    something: true
  },
  created: function () {
    var anyName = this // Save reference to this under another name
    axios.get('/uri').then(function () {
      this.something = false // no error here, but you are still creating new property
      anyName.something = false // NOW you are really changing "something" value in data
    })
  }
})

如您所見,您可以以任何名稱保存它。 但請遵循方便並將其命名為self 不是vm ,因為這個名字會再次讓你感到困惑,是否會與var vm = new Vue()發生沖突。 它不會,但不會混淆自己,只是將其命名為self

不試用箭頭函數,不要使用bind。 只需按照這個簡單的規則。 之后,你會更有經驗,你可以(並且應該)使用它們,但是現在,享受編碼,而不是調試:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM