Компонент шаблона Vuejs reactive v-if

#vue.js

#vue.js

Вопрос:

Я изо всех сил пытаюсь понять, как сделать мой компонент реактивным. На данный момент кнопка отображается правильно, но как только произойдет событие создания / удаления, шаблон не изменится. Есть какие-нибудь советы о том, как обновить компонент после того, как событие состоялось?

 new Vue({
  el: '#app'
});


Vue.component('favourite-button', {
  props: ['id', 'favourites'],
  template: '<input class="hidden" type="input" name="_method" value="{{ id }}" v-model="form.listings_id"></input><button v-if="isFavourite == true" class="favourited" @click="delete(favourite)" :disabled="form.busy"><i class="fa fa-heart" aria-hidden="true"></i><button class="not-favourited" v-else @click="create(favourite)" :disabled="form.busy"><i class="fa fa-heart" aria-hidden="true"></i></button><pre>{{ isFavourite == true }}</pre>',

  data: function() {
    return {
        form: new SparkForm({
            listings_id: ''
        }),
    };

  },


  created() {
      this.getFavourites();

  },

  computed: {
      isFavourite: function() {

        for (var i = 0; this.favourites.length; i  )
          {
            if (this.favourites[i].listings_id == this.id) {
            return true;

          }
        }
      },

    },

  methods: {

    getFavourites() {
        this.$http.get('/api/favourites')
          .then(response => {
            this.favourites = response.data;
          });
        },

    create() {
        Spark.post('/api/favourite', this.form)
            .then(favourite => {
            this.favourite.push(favourite);
            this.form.id = '';

            });


        },

        delete(favourite) {
            this.$http.delete('/api/favourite/'   this.id);
            this.form.id = '';

        }
      }

    });

Vue.component('listings',  {
    template: '#listing-template',

    data: function() {
      return {
            listings: [], favourites: [],
        };
    },

    created() {
        this.getListings();
    },

    methods: {
      getListings() {
          this.$http.get('/api/listings')
            .then(response => {
              this.listings = response.data;
          });
        }
      }
});
  

Ответ №1:

Vue ожидает, что разметка шаблона HTML будет идеальной. В противном случае вы столкнетесь с множеством проблем.

Я только что проверил ваш шаблон и обнаружил проблему — первый <button> элемент не закрывается.

Вот обновленная версия вашего кода:

 Vue.component('favourite-button', {
    props: ['id', 'favourites'],
    template: `
        <input class="hidden" type="input" name="_method" value="{{ id }}" v-model="form.listings_id"></input>
        <button v-if="isFavourite == true" class="favourited" @click="delete(favourite)" :disabled="form.busy">
            <i class="fa fa-heart" aria-hidden="true"></i>

        </button> <!-- This is missing in your version -->

        <button class="not-favourited" v-else @click="create(favourite)" :disabled="form.busy">
            <i class="fa fa-heart" aria-hidden="true"></i>
        </button>
        <pre>{{ isFavourite == true }}</pre>
    `,
    ...
  

Обратите внимание на комментарий в 7-й строке выше, закрывающий </button> тег отсутствует в вашем шаблоне.

В качестве дополнительного примечания, если вы не хотите вводить обратную косую черту в конце каждой строки, чтобы создавать многострочные строки шаблона, вы можете использовать обратные тики, как показано в моем примере кода выше. Это поможет вам избежать ошибок разметки, приводящих к проблемам с компонентами Vue и многочасовой отладке.

Еще одна ссылка: проверьте «Многострочные строки» на этой странице:https://developers.google.com/web/updates/2015/01/ES6-Template-Strings

Соответствующие строки (скопированы со страницы выше):

Любой пробел внутри синтаксиса обратной ссылки также будет считаться частью строки.

 console.log(`string text line 1
string text line 2`);
  

РЕДАКТИРОВАТЬ: обнаружена возможная ошибка в коде

Вот еще одна проблема в вашем create методе favourite-button компонента:

 methods: {
    // ...
    create() {
        Spark.post('/api/favourite', this.form)
            .then(favourite => {
                this.favourite.push(favourite);  // Note: This is the problem area
                this.form.id = '';
            });
    },
    //...
}
  

Ваш обработчик успеха ссылается на this.favourite.push(...) . У вас нет this.favourite в data или props вашего компонента. Разве это не должно быть this.favourites ?

Комментарии:

1. Спасибо, мани, я не заметил </button>, я также перенял вашу обратную ссылку для многострочных шаблонов — очень полезно!

2. Однако это не исправило реактивность кнопки. Я все еще изучаю решение.

3. @BenF Можете ли вы проверить мои правки в ответе выше? В вашем create методе favourite-button компонента есть потенциальная ошибка.

4. принял к сведению и благодарит. По какой-то причине оба this.favourite.push(favourite); и this.favourites.push(favourite); работают. Проблема в том, что я не вижу кнопку реактивной, потому что я не вызываю isFavourite динамически data ?

5. Я удивлен, что this.favourite.push работает, так как в идеале он должен выдавать ошибку типа cannot invoke push on undefined . Тем не менее, ваше isFavourite является вычисляемым свойством, которое мне кажется нормальным. Он не обязательно должен быть частью вашего data , если вы правильно вычисляете его значение. Это не похоже на проблему с визуализацией Vue, но логику вашего приложения необходимо тщательно оценить, используя console.log во многих местах, используя предварительно определенные тестовые данные, для которых вы знаете результат. Самое главное, вам нужно проверить вычисляемое свойство на isFavourite правильность логики.