Vue-在v-for循环中返回Promise

时间:2019-02-05 08:02:57

标签: javascript vuejs2 fetch vue-component es6-promise

我在使用Vue JS时遇到问题。我正在遍历WordPress Rest API的一些“帖子”,并且必须为每个帖子在v-for循环内打印该帖子的作者。分配给帖子的作者只是一个ID,因此我必须对API进行新的调用,才能根据返回的ID获得作者的名字。

我遇到的问题是,当我调用获取作者姓名的函数时,它会在分配给posts对象中所有帖子的所有用户之间不断地来回切换。

Vue.component('blog-posts', {
    props: {
        posts: {},
    },

    data() {
        return {
            userName: '',
        }
    },

    template: `
        <section class="entry" v-if="posts.length">
            <div class="entry-content">
                <article v-for="(post, index) in posts" :key="post.index">
                    <h1><a :href="post.link">{{ post.title.rendered }}</a></h1>
                    <p v-html="post.content.rendered"></p>

                    // THIS IS THE PROBLEM
                    <p v-if="getAuthor(post.author)">{{ userName }}</p>

                    <button type="submit" @click="deletePost(post)">Slet indlæg</button>
                </article>
            </div>
        </section>
    `,

    created() {
        // Of course it works if i put a constant user id in, but i need to parse in inside the loop.
        // this.getAuthor(2);
    },

    computed: {

    },

    methods: {
        deletePost: function(post) {
            let path = new wp.api.collections.Posts({
                id: post.id
            });

            Event.$emit('delete-post', path, post.id);
        },


        getAuthor(author) {
            let vm = this;

            let user = new wp.api.models.User({
                id: author,
            });

            return user.fetch().then(response => {
                vm.userName = response.name;
                // return true;
            });
        },

        // showAuthor(author) {
        //  let user = new wp.api.models.User({
        //      id: author
        //  });

        //  user.fetch().then(response => {
        //      this.userName = response.name;
        //      // return true;
        //  });
        // },
    },

});



const app = new Vue({
    el: '#app',
    data: {
        wp: wp.api,
        message: 'Hello Vue',
        posts: [],
    },

    mounted() {
        let posts = new wp.api.collections.Posts();
        let response = posts.fetch().then(response => {
            this.posts = response;
        });

        Event.$on('post-added', (item) => {
            this.posts.unshift(item.attributes);
        });

        // Delete post
        Event.$on('delete-post', (item, id) => {
            this.posts.forEach((post, index) => {
                if ( post.id === id ) {
                    this.posts.splice(index, 1);
                    item.at(0).destroy();
                }
            });
        });
    },
});

我不完全确定这是返回函数调用值的最佳方法。

2 个答案:

答案 0 :(得分:1)

您的问题是您的blog-posts组件包含多个博客帖子,但是它们都共享对username的单个引用。由于博客帖子可能是由不同的人撰写的,因此您在遍历各个帖子时当然会多次覆盖username

最好的解决方案实际上是将单个博客帖子抽象到其自己的原子组件中,例如,您的<blog-posts>组件只是多个<blog-post>的容器:示意上,它应该像这样:

└─ <blog-posts>
    ├─ <blog-post>
    ├─ <blog-post>
    ├─ <blog-post>
    ├─ <blog-post>
    └─ <blog-post>

您可以使用:post="post",以便将整个post数据传递到您的原子组件中:

// The `<blog-posts>` component is only a COLLECTION of `<blog-post>`
// So it is a "dumb" component in a sense
Vue.component('blog-posts', {
    props: {
        posts: {},
    },
    template: `
        <section class="entry" v-if="posts.length">
            <div class="entry-content">
                <blog-post v-for="(post, index) in posts" :key="post.index" :post="post" />
            </div>
        </section>
    `
});

所有与帖子相关的逻辑都应从<blog-posts>集合组件中删除,而应移至原子<blog-post>组件中。然后,在新的<blog-post>组件中,您可以:

  • 处理单个帖子的所有模板需求
  • 处理单个帖子操作,例如帖子删除
  • 最重要的是:使用mounted()生命周期挂钩执行API调用以获取与该个人帖子有关的用户名

因此,您的原子组件代码将如下所示:

// The `<blog-post>` component is atomic
// It contains all the information related to a SINGLE post
Vue.component('blog-post', {
    props: {
        post: {},
    },

    data() {
        // Each individual blog post stores its own username
        return {
            userName: '';
        }
    },

    template: `
        <article>
            <h1><a :href="post.link">{{ post.title.rendered }}</a></h1>
            <p v-html="post.content.rendered"></p>

            <p>{{ userName }}</p>

            <button type="submit" @click="deletePost(post)">Slet indlæg</button>
        </article>
    `,

    methods: {
        deletePost: function(post) {
            let path = new wp.api.collections.Posts({
                id: post.id
            });

            Event.$emit('delete-post', path, post.id);
        }
    },

    mounted: function() {
        // Fetch post author metadata when the `<blog-post>` component is mounted
        let user = new wp.api.models.User({
            id: author,
        });

        user.fetch().then(responsve => this.userName = response.name);
    }

});

答案 1 :(得分:0)

显示侧的所有内容均应具有反应性。您不应该在模板的v-if中调用任何方法。您不知道/不应该在何时渲染模板。

尝试定义一个data来保存您的作者详细信息,然后从创建的挂钩中调用getAuthor()