通过rest api - wordpress和vuejs按类别获取帖子

时间:2018-04-26 21:57:08

标签: wordpress rest vue.js vuejs2 wordpress-rest-api

我正在尝试通过Wordpress Restful API获取一些帖子数据。我到目前为止所做的是:

  1. 加载应用时,抓取帖子的第一页。
  2. 然后,如果用户点击“加载更多帖子”按钮,另一页帖子 获取,直到没有更多帖子显示
  3. 首先,我在main.js文件中创建了这个函数:

    Array.prototype.next = function*(){
      for(let item of this){
        yield item
      }
    }
    

    然后在App.vue中,我有这个:

    created(){
        this.$store.dispatch('setCategories') //grab posts categories
          .then(resolve=> this.$store.dispatch('setPostsCount')) //grab the number of post pages and the total number of posts
            .then(resolve=>this.$store.dispatch('loadPosts')) load the first page of posts
              .catch(err => console.log(err))
      }
    

    这是商店模块post.js:

      import axios from 'axios'
    
    const postsRequest = axios.create({
        baseURL: 'https://wordpress-site/wp-json/wp/v2/posts'
      })
    
    
    
    
    
    
    const state = {
        posts:[],
        filteredPosts:[],
        totalPages:null,
        totalPosts:null
    }
    
    
    const getters = {
        getPosts(state){
            return  state.posts
        },
        getFilteredPosts(state){
            return state.filteredPosts
        },
        getAllPostsPages(state){
            return state.totalPages
        },
        getAllPostsNumber(state){
            return state.totalPosts
        },
        getNextPage(state,getters){
            return getters.getAllPostsPages.next()
        }
    }
    
    
    const mutations = {
        'SET_POSTS_COUNT'(state,headers){
            state.totalPages = [...Array(parseInt(headers['x-wp-totalpages'])).keys()].map(page => page+1),
            state.totalPosts = parseInt(headers['x-wp-total']) //[...Array(parseInt(headers['x-wp-total'])).keys()]
        },
        'LOAD_POSTS'(state,posts){
            for(let post of posts){
                state.posts.push(post)
            }
            console.log(state.posts.length)   
        },
        'FILTER_BY_CATEGORY'(state,posts){
            state.filteredPosts = []
            state.filteredPosts = posts
        },
        'EMPTY_FILTERED_POSTS'(state){
            state.filteredPosts = []
        }
    }
    
    
    const actions = {
        setPostsCount({commit}){
            return new Promise((resolve,reject)=>{
                postsRequest.get().then(response => {
                    commit('SET_POSTS_COUNT',response.headers)
                    resolve()
                })  
            })
    
        },
        loadPosts({commit,getters}){
            let nextPage = getters.getNextPage.next()
            if(!nextPage.done){
                postsRequest.get(this.baseURL,{
                    params:{
                        page: nextPage.value
                    }
                }).then(response=> {
    
                    commit('LOAD_POSTS',response.data)
                })
                .catch(err => console.log(err))
            }
        },
        loadPostsByCategory({commit,getters},index){
                postsRequest.get(this.baseURL,{
                    params:{
                        categories:index
                    }
                }).then(response => commit('FILTER_BY_CATEGORY',response.data))
                    .catch(err => console.log(err))
    
        },
        loadPostsByCat({commit,getters},category){
            ...
        }
    }
    
    export default {
        state,
        getters,
        actions,
        mutations
      }
    

    这是我显示帖子的组件:

     <template>
        <div class="gy-read">
            <div @click="emptyFilteredPosts()">all</div>
            <div style="display:inline-block;margin-left:20px" v-for="category in categories" :key="category.id">
                <h3 @click="searchByCategory(category.index)">{{category.name}}</h3>
            </div>
            <div v-for="post in posts" :key="post.id">
                <h2>{{post.title.rendered}}</h2>
                <h4>{{post.date}}</h4>
                <h4>{{post.categories}}</h4>
            </div>
            <div>
                <button v-if="!currentCategory" @click="loadMorePosts()">load more</button>
                <button v-else @click="loadMorePostsByCat()">load more cat</button>
            </div>
    
    
        </div>
    
    </template>
    
    <script>
    
    export default {
        data(){
            return{
                currentCategory:null,
            }
        },
     computed:{
         posts(){
             return this.$store.getters.getFilteredPosts.length ? this.$store.getters.getFilteredPosts : this.$store.getters.getPosts
         },
         categories(){
             return this.$store.getters.getCategories //this simply create an array of category index
         },
     },
     methods:{
         loadMorePosts(){
            this.$store.dispatch('loadPosts')
    
         },
         loadMorePostsByCat(){
             this.$store.dispatch('loadPostsByCat',this.currentCategory)
         },
         searchByCategory(index){
            this.currentCategory = index;
            this.$store.dispatch('loadPostsByCategory',index)
         },
         emptyFilteredPosts(){
             this.$store.commit('EMPTY_FILTERED_POSTS');
             this.currentCategory = null;
         }
     }
    
    }
    </script>
    
    <style lang="scss">
        .gy-read{
            margin-top:150px;
        }
    </style>
    

    现在我陷入困境:一旦用户点击某个类别,state.posts列表将替换为state.filteredPosts列表,其中包含通过Rest api按类别提取的前10个帖子(请参阅{{1} } 方法)。

    现在,我希望searchByCategory按钮仅在具有相同类别的帖子列表中升级帖子列表,以及已经存在的帖子。

    这可能吗,或者我必须重新考虑我的实施?

    此实施仅适用于帖子总数, 无论分类如何。

    我无法修改php,我只能使用vue。

    谢谢!

1 个答案:

答案 0 :(得分:0)

好的,我这样解决了。正如Sphinx建议的那样,当类别更改时,我将post的数组重置为0,并使用已存在的帖子数量的偏移量来发出另一个请求。似乎这有效:

成分:

<template>
    <div class="gy-read">
        <div class="category">
            <div @click="currentCategory='all'">all</div>
            <div v-for="category in categories" :key="category.id">
                <h3 @click="currentCategory = category.index">{{category.name}}</h3>
            </div>
        </div>
        <div class="card__container">
            <router-link tag='div' class="card" :to="{name:'article', params: {slug: post.slug, post:post}}" v-for="post in posts" :key="post.id">
            <div :style="{ backgroundImage: 'url(' + post.better_featured_image.source_url+ ')' }" class="card__img"></div>
            <div class="card__content">
                <h2>{{post.title.rendered}}</h2>
                <span v-for="cat in post.categories" :key="cat">{{ cat}}</span>
            </div>  
        </router-link>
        </div>
        <div class="load">
            <button ref="button" v-if="posts.length" @click="loadMorePosts()">load more</button>
        </div>


    </div>

</template>

<script>
export default {
    data(){
        return{
            currentCategory:null,
        }
    },
    created(){

    },
 computed:{
     posts(){
         return this.$store.getters.getPosts
     },
     categories(){
         return this.$store.getters.getCategories
     }

 },
 watch:{
     currentCategory: function(cat){
         console.log(cat)
         this.$store.commit('RESET_POSTS')
         this.loadMorePosts()
     }

 },
 methods:{
     loadMorePosts(){
        this.$store.dispatch('loadPosts',this.currentCategory)
     },
 }

}
</script>

存储

import axios from 'axios'


const state = {
    posts:[]
}


const getters = {
    getPosts(state){
        return  state.posts
    },
}

const mutations = {
    'LOAD_POSTS'(state,posts){
        for(let post of posts){
            state.posts.push(post)
        }  
    },
    'RESET_POSTS'(state){
        state.posts = []
    },
}


const actions = {
    loadPosts({commit,getters},category){
            axios.get('/posts',{
                params:{
                    categories: category === 'all' ? null : category,
                    offset: getters.getPosts.length
                }
            }).then(response=> {
                if(response.data.length){
                    console.log(response.data)
                    commit('LOAD_POSTS',response.data)
                }else{
                    //this._vm.$emit('noMorePosts',null)

                }

            })
            .catch(err => console.log(err))



    }
}

export default {
    state,
    getters,
    actions,
    mutations
  }

App.vue创建了hook:

created(){
    this.$store.dispatch('setCategories')
        .then(resolve=>this.$store.dispatch('loadPosts','all'))
          .catch(err => console.log(err))
  }