过滤掉Vue中的重复数据

时间:2018-08-05 20:43:59

标签: vue.js vuejs2 vuetify.js vue-filter

如何过滤列表中的重复标签,以便仅列出每个标签中的一个?

这是我的组件代码:

  <template>
    <v-layout row wrap>

    <ul>
      <li v-for="post in sortByName(posts)" :key="post.key">
       <v-chip
         v-for="i in sortByName(post.tags)"
         :key="i.key"
         :color="`${i.color} lighten-3`"
         label
         small
       >
          <span class="pr-2">
            {{ i.text }}
          </span>
        </v-chip>
      </li>
    </ul>

  </v-layout>
  </template>

  <script>
    import { mapState } from 'vuex'
    const fb = require('../firebaseConfig.js')

    export default {
      data: () => ({

      }),
      computed: {
        ...mapState(['posts'])
    },
    methods: {
      // function to put the tags in the right order to a -> z
      sortByName (list) {
        return _.orderBy(list, 'text', 'asc');
      }
     }
    }
  </script>

例如,在下面的屏幕快照中,我想过滤掉Beach,以便在列表中只看到一次Beach

screenshot

数据如下: data format

1 个答案:

答案 0 :(得分:2)

一种解决方案是使用computed property来返回filteredPosts的新列表(例如posts),并过滤其tags数组。在下面的示例中,calculated属性内部的缓存用于跟踪标签。计算的处理程序maps this.posts[]进入新的Arrayfilters每个条目的tags[],跟踪缓存中的新标记为“可见”,并删除已经存在的标记“看到”。

模板:

<li v-for="post in filteredPosts" :key="post.key">

脚本:

computed: {
  filteredPosts() {
    const tagCache = {};
    const newPosts = this.posts.map(post => {
      return {
        ...post,
        tags: post.tags.filter(tag => {
          const seen = tagCache[tag.text];
          tagCache[tag.text] = true;
          return !seen;
        })
      };
    });
    return newPosts;
  }
}

new Vue({
  el: '#app',
  data() {
    return {
      posts: [
        {
          key: 1,
          tags: [
            { color: 'blue', text: 'Sky' },
            { color: 'green', text: 'Tree' },
            { color: 'yellow', text: 'Beach' },
          ],
        },
        {
          key: 2,
          tags: [
            { color: 'purple', text: 'Grape' },
            { color: 'red', text: 'Apple' },
            { color: 'orange', text: 'Orange' },
          ],
        },
        {
          key: 3,
          tags: [
            { color: 'blue', text: 'Blueberry' },
            { color: 'yellow', text: 'Beach' },
          ],
        },
        {
          key: 4,
          tags: [
            { color: 'pink', text: 'Flower' },
            { color: 'yellow', text: 'Beach' },
          ],
        },
      ]
    };
  },
  methods: {
    // function to put the tags in the right order to a -> z
    sortByName (list) {
      return _.orderBy(list, 'text', 'asc');
    },
  },
  computed: {
    filteredPosts () {
      const tagCache = {};
      // map `posts` to a new array that filters
      // out duplicate tags
      const newPosts = this.posts.map(post => {
          return {
            ...post,
            tags: post.tags.filter(tag => {
              const seen = tagCache[tag.text];
              tagCache[tag.text] = true;
              return !seen;
            })
          };
        });
      return newPosts;
    }
  }
})
@import 'https://unpkg.com/vuetify@1.1.9/dist/vuetify.min.css'
<script src="https://unpkg.com/vue@2.5.17"></script>
<script src="https://unpkg.com/lodash@4.17.10/lodash.min.js"></script>
<script src="https://unpkg.com/vuetify@1.1.9/dist/vuetify.min.js"></script>

<div id="app">
  <v-app id="inspire">
    <v-container fluid class="pa-0">
      <v-layout row wrap>
        <ul>
          <li v-for="post in filteredPosts" :key="post.key">
            <v-chip v-for="i in sortByName(post.tags)"
                    :key="i.key"
                    :color="`${i.color} lighten-3`"
                    label
                    small>
              <span class="pr-2">
                {{ i.text }}
              </span>
            </v-chip>
          </li>
        </ul>
      </v-layout>
    </v-container>
  </v-app>
</div>

相关问题