Почему `this` внутри filter() становится неопределенным в VueJS?

avatar
Sanjay
8 апреля 2018 в 03:09
4253
1
8

Я создаю форму DOB.

Я использую VueJS в форме. Сначала пользователь должен указать дату месяца, чтобы день отображался в соответствии с количеством дней в соответствующем месяце.

Я использую filter(), но проблема в том, что this внутри filter() не определено. Как это исправить?

new Vue ({
  el: '.app',
  data: {
    months: [
      {month: 'January', days: 31},
      {month: 'February', days: 28},
      {month: 'March', days: 31},
      {month: 'April', days: 30},
      {month: 'May', days: 31},
      {month: 'June', days: 30},
      {month: 'July', days: 31},
      {month: 'August', days: 31},
      {month: 'September', days: 30},
      {month: 'October', days: 31},
      {month: 'November', days: 30},
      {month: 'December', days: 31},
    ],
    selectedMonth: []
  },
  computed: {
    filterDays() {
      return this.months.filter(function(value) {
        return value.month === this.selectedMonth;
      });
    }
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div class="app">
  <select id="dobd">
    <option v-for="day in filterDays[0].days" :value="day">{{ day }}</option>
	</select>
</div>

Я знаю, что использование глобальной переменной может быть решением, но я хочу использовать selectedMonth внутри data() из-за своих собственных потребностей.

Источник

Ответы (1)

avatar
acdcjunior
8 апреля 2018 в 03:12
13

С function () {} контекст (this) теряется. Это означает, что внутри функции аргумента filter this не будет экземпляром Vue.

Есть несколько возможных решений:

  • Использовать функции со стрелками (предпочтительно):

    filterDays() {
      return this.months.filter((value) => {
        return value.month === this.selectedMonth;
      });
    }
    
  • Использовать .bind():

    filterDays() {
      return this.months.filter(function(value) {
        return value.month === this.selectedMonth;
      }.bind(this));
    }
    
  • Использовать локальную переменную вне функции:

    filterDays() {
      let vm = this;
      return this.months.filter(function(value) {
        return value.month === vm.selectedMonth;
      });
    }
    

Демо:

new Vue ({
  el: '.app',
  data: {
    months: [
      {month: 'January', days: 31},
      {month: 'February', days: 28},
      {month: 'March', days: 31},
      {month: 'April', days: 30},
      {month: 'May', days: 31},
      {month: 'June', days: 30},
      {month: 'July', days: 31},
      {month: 'August', days: 31},
      {month: 'September', days: 30},
      {month: 'October', days: 31},
      {month: 'November', days: 30},
      {month: 'December', days: 31},
    ],
    selectedMonth: 'January' // changed to a valid month
  },
  computed: {
    filterDays() {
      return this.months.filter((value) => {
        return value.month === this.selectedMonth;
      });
    }
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div class="app">
  <select id="dobd">
    <option v-for="day in filterDays[0].days" :value="day">{{ day }}</option>
  </select>
</div>
Sanjay
8 апреля 2018 в 03:16
0

days теперь не определено :(

acdcjunior
8 апреля 2018 в 03:19
0

Это потому, что у вас не было действительного this.selectedMonth. Смотрите демо в ответе (только что добавлено).