Vue过滤掉重复数据

Filter out duplicate data in Vue

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

这是我的组件代码:

  <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一次:

数据如下所示:

一个解决方案是使用 computed property that returns a new list (e.g., filteredPosts) of posts with its tags array filtered. In the example below, a cache inside the computed property is used to track tags. The computed handler maps this.posts[] into a new Array and filters 每个条目的 tags[],跟踪缓存中的新标签作为 "seen" 并删除已经 "seen".[=24= 的标签]

模板:

<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>