Vue - вернуть обещание в цикле v-for - PullRequest
0 голосов
/ 05 февраля 2019

У меня проблема с Vue JS.Я перебираю некоторые «сообщения» из API WordPress Rest, и мне приходится печатать автора сообщения внутри цикла v-for для каждого сообщения.Автор, назначенный сообщению, является только идентификатором, поэтому я должен сделать новый вызов API, чтобы получить имя автора на основе возвращенного идентификатора.

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

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 голосов
/ 05 февраля 2019

Ваша проблема в том, что ваш 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);
    }

});
0 голосов
/ 05 февраля 2019

Все на стороне дисплея должно быть реактивным.Вы не должны вызывать метод, любой метод в v-if шаблона.Вы не знаете / не должны заботиться о том, когда шаблон отображается.

Попробуйте определить data для хранения сведений об авторе, а затем вызвать getAuthor() из созданного хука.

...