让 Vue 更新 view/component

Get Vue to update view/component

我正在处理一个组件,正处于十字路口。

我有以下组件"RecentUpdates"

在其中,我将 props 传递给其他几个组件,正如您从文件顶部看到的那样。

我的问题是在添加新的 post 时,我无法弄清楚如何取回正确的更新对象数组,我也无法弄清楚正确的 'Vue way' 来更新数据传递给 "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>

尝试在事件侦听器中使用 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
       }
    }
 }

所以我在阅读您的代码时发现了很多问题。

  1. 你有一个recent_posts数据属性,它是一个数组。当您进行 ajax 调用以获取 post 时,您将 也是 数组的响应推送到 recent_posts 数组中。为什么?为什么不直接设置 recent_posts = response.data?这样你就不用绕着recent_posts[0]转了。
  2. 您正在观察程序中设置 EventBus 处理程序。这真的很不寻常。通常,您会在 createdmounted.
  3. 中设置处理程序 EventBus 处理程序中的
  4. this 可能指的是 EventBus 而不是您的 Vue。理想情况下,您可以将处理程序设置为组件上的一个方法,该组件已经绑定到 Vue.类似于 EventBus.$on("addPost", this.addPost).
  5. 完成所有这些后,添加新的 post 应该像 this.recent_posts.push(newPost).
  6. 一样简单

以下是我可能会推荐的内容。

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
  },
}