Получить Vue, чтобы обновить вид / компонент

Я застрял на перекрестке с компонентом, над которым я работаю.

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

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

Моя проблема заключается в том, что при добавлении нового сообщения я не могу понять, как вернуть правильный массив объекта обновления, и я также не могу найти правильный "путь Vue" для обновления данных, которые передаются в "PostList". " составная часть.

<template>
  <div>
    <PostFilter v-on:selectedCategory="getSelectedPosts" v-on:showAllPosts="showAllPosts" :user="user" :categories="categories"/>

    <PostList v-if="recent_posts[0]" :categories="categories" :posts="recent_posts[0]" :user="user"/>

    <Pagination v-on:getPreviousPage="getPreviousPage" v-on:getNextPage="getNextPage"/>
  </div>
</template>

<script>

import PostList from './PostList';
import PostFilter from './PostFilter';
import Pagination from './Pagination';
import EventBus from '../event-bus';


export default {

  name: 'RecentUpdates',

  data: () => ({
    errors: [],
    recent_posts: [],
  }),

  props: ['categories', 'user'],

  components: {
    PostList,
    PostFilter,
    Pagination
  },

  created() {

    if (this.user.meta.selected_categories[0] == 0) {
      this.showAllPosts();
    }

    // do not call here, not working as expected
    // is switching selected category to an incorrect one
    // this.updateList();

    this.getSelectedCategory();
  },

  watch: {
    recent_posts: function(newValue) {

      EventBus.$on('addPost', function(newPost) {
        console.log(newPost);

        this.$forceUpdate();


        //this.recent_posts.push(newPost);

        //this.$set(this.recent_posts, newPost, newPost);

        // this.$nextTick(function () {
        //   this.recent_posts.push(newPost);
        // });


      });

        console.log(this.recent_posts[0]);


      // this.$nextTick(function () {
      //   console.log(this.recent_posts[0]) // => 'updated'
      // });

      // if (this.user.meta.selected_categories[0] == 0) {
      //   EventBus.$on('addPost', this.showAllPosts);
      // } else {
      //   EventBus.$on('addPost', this.getSelectedCategory);
      // }
      //this.updateList();
    }
  },

  methods: {

    // updateList() {

    //   if (this.user.meta.selected_categories[0] == 0) {
    //     EventBus.$on('addPost', this.showAllPosts);
    //     //EventBus.$emit('newPost');

    //   } else {
    //     EventBus.$on('addPost', this.getSelectedCategory);
    //     //EventBus.$emit('newPost');
    //   }

    // },

    getSelectedCategory() {

      let categoryId = this.user.meta.selected_categories[0];

      this.getSelectedPosts(categoryId);
    },

    showAllPosts() {

      axios.get('/wp-json/wp/v2/posts?_embed=true&status=[publish,resolved,unresolved]', 
        {headers: {'X-WP-Nonce': portal.nonce}})
      .then(response => {
        this.recent_posts = [];
        //this.recent_posts = response.data;
        //console.log(response.data);
        this.recent_posts.push(response.data);
        console.log(this.recent_posts[0]);

      })
      .catch(e => {
        this.errors.push(e);
      });
    },

    getSelectedPosts(categoryId) {

      axios.get('/wp-json/wp/v2/posts?_embed=true&status=[publish,resolved,unresolved]&categories=' + categoryId,
        {headers: {'X-WP-Nonce': portal.nonce}})
      .then(response => {
        this.recent_posts = [];
        //console.log(response.data);

        this.recent_posts.push(response.data);

        console.log(this.recent_posts[0]);


      })
      .catch(e => {
        this.errors.push(e);
      });
    },

    /**
     * Pagination methods
     *
     */
    getPreviousPage(page) {
      axios.get('/wp-json/wp/v2/posts?_embed=true&status=[publish,resolved,unresolved]&page=' + page, 
        {headers: {'X-WP-Nonce': portal.nonce}})
      .then(response => {
        this.recent_posts = response.data;
      })
      .catch(e => {
        this.errors.push(e);
      });
    },

    getNextPage(page) {
      axios.get('/wp-json/wp/v2/posts?_embed=true&status=[publish,resolved,unresolved]&page=' + page, 
        {headers: {'X-WP-Nonce': portal.nonce}})
      .then(response => {
        this.recent_posts = response.data;
      })
      .catch(e => {
        this.errors.push(e);
      });
    }
  },
}

</script>

<style>

</style>

2 ответа

Решение

Так что я вижу ряд проблем при чтении вашего кода.

  1. У тебя есть recent_posts свойство данных, которое является массивом. Когда вы делаете ajax-вызов, чтобы получить сообщения, вы нажимаете ответ, который также является массивом в recent_posts массив. Зачем? Почему бы просто не установить recent_posts = response.data? Тогда вам не придется проходить мимо recent_posts[0] вокруг.
  2. Вы настраиваете свой EventBus обработчик внутри наблюдателя. Это действительно необычно. Обычно вы устанавливаете обработчик внутри created или же mounted,
  3. this Внутри обработчик EventBus, скорее всего, относится к EventBus, а не к вашему Vue. В идеале вы должны установить обработчик как метод для компонента, который уже связан с Vue. Что-то вроде EventBus.$on("addPost", this.addPost),
  4. После того, как вы все это сделали, добавление нового поста должно быть таким простым, как this.recent_posts.push(newPost),

Вот что я мог бы порекомендовать.

export default {
  name: 'RecentUpdates',
  data(){
    return {
      errors: [],
      recent_posts: []
    }
  },
  props: ['categories', 'user'],
  components: {
    PostList,
    PostFilter,
    Pagination
  },
  created() {
    if (this.user.meta.selected_categories[0] == 0) {
      this.showAllPosts();
    }
    this.getSelectedCategory();

    EventBus.$on("addPost", this.addPost)
  },
  beforeDestroy(){
    EventBus.$off("addPost", this.addPost)
  },
  methods: {
    getPosts(url){
      axios.get(url, {headers: {'X-WP-Nonce': portal.nonce}})
        .then(response => this.recent_posts = response.data)
        .catch(e => this.errors.push(e))
    },
    showAllPosts() {
      const url = '/wp-json/wp/v2/posts?_embed=true&status=[publish,resolved,unresolved]';
      this.getPosts(url);
    },
    getSelectedPosts(categoryId) {
      const url = '/wp-json/wp/v2/posts?_embed=true&status=[publish,resolved,unresolved]&categories=' + categoryId;
      this.getPosts(url);     
    },     
    addPost(newPost){
      this.recent_posts.push(newPost)
    },
    ... //other methods
  },
}

Попробуйте использовать kebab-case в слушателях событий вместо camelCase:

  1. Пример: v-on:selectedCategory="getSelectedPosts" должно быть v-on:selected-category="getSelectedPosts".
  2. Пример: v-on:showAllPosts="showAllPosts" должно быть v-on:show-all-posts="showAllPosts" или даже с использованием ярлыка @show-all-posts="showAllPosts".

ОБНОВЛЕНИЕ: Если вы можете предоставить код других компонентов, чтобы у нас было более четкое представление о вашей проблеме, но вы хотите отслеживать только изменения, которые происходят с объектом или массивом, в vue.js, вам нужно тщательно их отслеживать. Ваш наблюдатель должен быть:

 watch: {
    recent_posts: {
       deep: true,
       handler: function( oldValue, newValue) {
          console.log( "recent_posts has changed" );
          // A post has been added, updated or even deleted
       }
    }
 }
Другие вопросы по тегам