最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Vue JS v-for filter by unique - Stack Overflow

programmeradmin2浏览0评论

My pany is moving from Angular JS to Vue. It has been very smooth until I needed to replicate the functionailty of an Angular filter into VueJS. The original Angular filter looked like so:

JS

app.filter('unique', function () {
    return function (collection, keyname) {
        var output = [],
            keys = [];

        angular.forEach(collection, function (item) {
            var key = item[keyname];
            if (keys.indexOf(key) === -1) {
                keys.push(key);
                output.push(item);
            }
        });

        return output;
    };
});

In my Vue I have the following:

<select class="u-full-width" v-model="newPost.cat">
   <option value="" selected="selected">Choose a Category</option>
   <option v-for="post in posts | unique" selected>{{ post.cat }}</option>
</select>

I assume I can still use filters the same, but how do I go about replicating this?

My pany is moving from Angular JS to Vue. It has been very smooth until I needed to replicate the functionailty of an Angular filter into VueJS. The original Angular filter looked like so:

JS

app.filter('unique', function () {
    return function (collection, keyname) {
        var output = [],
            keys = [];

        angular.forEach(collection, function (item) {
            var key = item[keyname];
            if (keys.indexOf(key) === -1) {
                keys.push(key);
                output.push(item);
            }
        });

        return output;
    };
});

In my Vue I have the following:

<select class="u-full-width" v-model="newPost.cat">
   <option value="" selected="selected">Choose a Category</option>
   <option v-for="post in posts | unique" selected>{{ post.cat }}</option>
</select>

I assume I can still use filters the same, but how do I go about replicating this?

Share Improve this question asked Mar 16, 2017 at 21:45 AuzyAuzy 2,1552 gold badges27 silver badges36 bronze badges 3
  • What do you mean replicating this? And i thing in Vue2 filters are not supported, and you can use puted methods – Matej Marconak Commented Mar 16, 2017 at 21:49
  • Replicate may not be the right word, "mimicking the functionality" may be better. I want to achieve same thing I did in Angular in Vue system. – Auzy Commented Mar 16, 2017 at 21:56
  • 1 check answer by Tomasz Rup, this is propadly most conventional way for vuejs2. In vuejs version 1 was filter similar to angularjs 1, but in version 2 was deprecated - you can check this tutorial filters ways in vue2 – Matej Marconak Commented Mar 16, 2017 at 22:06
Add a ment  | 

2 Answers 2

Reset to default 9

You should use a puted property here. Filters in Vue are, as stated by the creator, supposed to be for text transformation mainly (not a rule of course, but I'd still go with a puted property).

On your ponent:

  puted: {
    uniquePosts: function() {
      var output = [];
      var keys   = [];

      this.posts.forEach(function (post) {
          var key = post[keyname];

          if (keys.indexOf(key) === -1) {
              keys.push(key);
              output.push(post);
          }
      });

      return output;
    }
  }

And v-for the uniquePosts in your template.

EDIT: To pass a keyname:

puted: {
   uniquePosts: function () {
      var vm = this;
      return function (keyname) {
         var output = [];
         var keys   = [];

         vm.posts.forEach(function (post) {
             var key = post[keyname];

             if (keys.indexOf(key) === -1) {
                 keys.push(key);
                 output.push(post);
             }
         });

         return output;
      };
   }
}

And you can call uniquePosts(keyname).

EDIT2: Fixed variable names, sorry

To improve on Tomasz' answer, you might define a global mixin in your main.js:

Vue.mixin({
  puted: {
    unique () {
      return function (arr, key) {
        var output = []
        var usedKeys = {}
        for (var i = 0; i < arr.length; i++) {
          if (!usedKeys[arr[i][key]]) {
            usedKeys[arr[i][key]] = true
            output.push(arr[i])
          }
        }
        return output
      }
    }
  }
})

In any of your ponents, pass in the array to filter and the property to filter on in:

<option v-for="post in unique(posts, 'cat')" selected>{{ post.cat }}</option>

Using an object to check which unique keys have been added should be more efficient than indexOf which has to search the array. Keep in mind you might want to make a Plugin instead of using a global mixin as the Vue docs remend.

发布评论

评论列表(0)

  1. 暂无评论