首页 文章

使用计算属性使用Vue按类别过滤帖子

提问于
浏览
0

我正在使用Vue 2创建可根据类别排序的帖子列表 . 类别选择输入是我正在使用自定义组件的按钮 . 目标是根据点击的类别过滤帖子列表(每个帖子可以属于多个类别) .

这在使用filteredBy的Vue 1中非常简单,但我在使用计算属性的Vue 2中失败了 .

Vue实例:

const port = new Vue( {
        el: '#portfolio-app',
        data: {
            portfolio: {},
            portfolioCats: {},
            portfolioLoading: true,
            categorySort: ''
        },
        created: function() {
            let $this = this;

            //2 requests will be sent: 1 one for the CPT, and one for the custom taxonomy
            let request = new XMLHttpRequest();
            let catsRequest = new XMLHttpRequest();

            //The request for the CPT

            request.onload = function() {
                $this.portfolio = JSON.parse( request.responseText );
                $this.portfolioLoading = false;
            };

            request.onerror = function() {
                console.log( 'A connection error has occurred' );
            };

            request.open( 'GET', endPoint, true );

            request.send();

            //The request for the custom taxonomy
            catsRequest.onload = function() {
                $this.portfolioCats = JSON.parse( catsRequest.responseText );
            };

            catsRequest.onerror = function() {
                console.log( 'A connection error occurred' );
            };

            catsRequest.open( 'GET', catsEndPoint, true );

            catsRequest.send();
        },
        computed: {
            categorySort: function () {
                let $self = this;
                return $self.portfolio.filter( ( portfolio ) => {
                    return portfolio.portfolio_category.match( $self.categorySort );
                } );

            }
        }
    } );

排序按钮组件:

Vue.component( 'sort-button', {
        props: ['value', 'cat'],
        template: `
          <input type="button" class="button sort-button button-accent"
            v-bind:value="cat.name"
            v-on:input="$emit( 'input', $event.target.value )"
          >
        `
    }
);

模板:

<div class="portfolio-categories-wrapper">
            <sort-button v-for="cat in portfolioCats" :cat="cat" v-model="categorySort"></sort-button>
        </div><!--ends portfolio-categories-wrapper-->

        <div class="portfolio-wrapper">

            <figure class="portfolio-item" v-for="post in categorySort">

                <a v-bind:href="post.link">
                    <img v-bind:src="post._embedded['wp:featuredmedia'][0].media_details.sizes.medium.source_url">
                </a>
                <figcaption class="portfolio-caption"><a v-bind:href="post.link"><span v-html="post.title.rendered"></span></a></figcaption>
            </figure>

        </div><!--ends portfolio-wrapper-->

请注意,计算属性中的“portfolio_category”是每个项目组合项中的整数数组 .

这样可以避免错误,但不会显示任何项目 .

任何帮助表示赞赏 .

1 回答

  • 0

    基于另一个动态列表过滤列表的关键是确保后者是被动的 . 见Reactivity in Depth .

    这是一个快速演示,按选定的类别过滤项目:

    new Vue({
      el: '#app',
      computed: {
        filteredItems () {
          return this.items.filter(i => this.selectedCategories.includes(i.category_id))
        }
      },
      data () {
        return {
          items: [],
          categories: [],
          selectedCategories: []
        }
      },
      methods: {
        selected (c) {
          return this.selectedCategories.includes(c.id)
        },
        toggle (c) {
          if (!this.selectedCategories.length) {
            this.selectedCategories.push(c.id)
          } else {
            const index = this.selectedCategories.findIndex(i => i === c.id)
            if (index !== -1) {
              this.selectedCategories.splice(index, 1)
            } else {
              this.selectedCategories.push(c.id)
            }
          }
        }
      },
      created () {
        this.categories = Array.from({length: 3}, (x, i) => {
          return {
            id: i + 1,
            text: `Category ${i + 1}`
          }
        })
        this.selectedCategories.push(...this.categories.map(c => c.id))
        this.items = Array.from({length: 20}, (x, i) => {
          return {
            id: i,
            text: `Item ${i + 1}`,
            category_id: Math.floor(Math.random() * 3) + 1
          }
        })
      }
    })
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      <p>Click to toggle active categories</p>
      <ul style="list-style-type: none; display: flex; flex-direction:row; justify-content: space-around">
        <li :style="{ display: 'inline-block', backgroundColor: selected(c) ? 'rgba(165,214,167,1)' : 'rgba(176,190,197,1)', padding: '1rem', border: selected(c) ? '1px solid black' : '' }" v-for="(c, i) in categories" :key="i" @click="toggle(c)">{{ c.text }}</li>
      </ul>
      <h4>Filtered Items</h4>
      <ul v-if="filteredItems.length" style="list-style-type: none; display: flex; flex-direction:row; flex-wrap: wrap; justify-content: space-around">
        <li style="border: 1px solid black; display: inline-flex; padding: 1rem; width: 12.5%" v-for="(c, i) in filteredItems" :key="i" @click="toggle(c)">{{ c.text }} - Category {{ c.category_id }}</li>
      </ul>
      <p v-else>No Items</p>
    </div>
    

相关问题