Свойство компонента класса Vue не определено в экземпляре

#javascript #typescript #vue.js #vue-component #vue-class-components

#javascript #typescript #vue.js #vue-компонент #vue-class-components

Вопрос:

У меня проблема в том, что мой пользовательский интерфейс каким-то образом не обновляется после того, как приложения извлекают некоторые данные из серверной части сервера.

У меня есть следующий код:

 <template>
  <div v-if="restaurant">
    <div class="center logo-container">
        <img class="img-fit" v-bind:src="'/api/restaurant/logo/'   restaurant.id" alt=""/>
    </div>
    <h2 class="title center dm-text-header">{{ restaurant.name }}</h2>
    <h4 class="subheading center">{{ restaurant.address.street }}, {{ restaurant.address.city }}</h4>     
  </div>
</template>

<script lang="ts">
import axios from 'axios';
import { Options, Vue } from "vue-class-component";
import { Tag } from "./Tag";
import { Restaurant } from "./Restaurant";

@Options({
  props: {
  }
})
export default class Menu extends Vue {  
  // hardcoded for testing 
  restaurantId =  "8ykw9ljq";   

  tagUrl = "/api/menu/"   this.restaurantId   "/tags";
  restaurantUrl = "/api/restaurant/"   this.restaurantId;

  restaurant!: Restaurant;
  tags: Tag[] = [];

  mounted() {
    // get tags
    this.getTags();
    // get restaurant
    this.getRestaurant();
  }

  getRestaurant(): void {
    axios.get<Restaurant>(this.restaurantUrl)
    .then(res => {
      this.restaurant = res.data;
    });
  }

  getTags(): void {
    axios.get(this.tagUrl)
    .then(res => {
      this.tags = res.data;
    });
  }

}
</script>
 

Я проверил, что серверная часть действительно обслуживает правильный ресторан, и зарегистрировал результаты после завершения вызова axios. Проблема в том, что DOM не обновляется. Если я добавлю следующее к DOM, DOM будет обновлен:

 <template>
...
  <div>
    {{tags}}
  </div>
<template>
 

Мне кажется, что vue каким-то образом обновил DOM только в том случае, если он распознает изменения в уже инициализированном пустом массиве, но не в текущем неинициализированном объекте restaurant.

Далее я получаю предупреждение: [Vue warn]: Property "restaurant" was accessed during render but is not defined on instance. о v-if том, что я нахожу странным, потому что это точная причина, по которой оно существует. Как мне нужно инициализировать ресторан, чтобы обновление через axios правильно распозналось vue?

Ответ №1:

Попробуйте объединить Typescript с null :

 restaurant: Restaurant | null = null;
 

Из документации по компоненту класса Vue:

Обратите внимание, что если начальное значение не определено, свойство класса не будет реагировать, что означает, что изменения свойств не будут обнаружены

и

Чтобы избежать этого, вы можете использовать значение null или вместо этого использовать перехват данных:

 import Vue from 'vue'
import Component from 'vue-class-component'

@Component
export default class HelloWorld extends Vue {
  // `message` will be reactive with `null` value
  message = null

  // See Hooks section for details about `data` hook inside class.
  data() {
    return {
      // `hello` will be reactive as it is declared via `data` hook.
      hello: undefined
    }
  }
}