Vue订单列表视图

时间:2016-12-19 11:52:51

标签: list sorting vue.js

我一直在项目上使用vue js 1.27,我需要能够按数值,字母和反向顺序对列表进行排序。 我整天都在尝试这一点而没有取得太大进展。

我在代码示例中留下了以前的一些代码,让您知道我已尝试过的内容。

谢谢

{% extends 'base.html.twig' %}

{% block body %}

<div id="wrap">
    <h2>Select a category</h2> 
    <ul id="categorySelect">
        <li v-for="cat in categories | orderBy reverse" @click="selectCategory(cat)" class="${cat.selectedCategory == category ? 'selected' : ''}">${cat.title}</li>
    </ul>
</div>

{% endblock %}

{% block javascripts %}

    <script type="text/javascript">

        Vue.config.delimiters = ['${', '}'];

        new Vue({
        el: '#wrap',
        data: {
            //reverse: -1,
            wasClicked: true,
            selectedCategory: null,
            categories: [{
                title: 'ALL',
                category: null
            }, 
            {
                title: 'CATE',
                category: 'sport'
            }, 
            {
                title: 'DOG',
                category: 'sport'
            },
            {
                title: 'SPEED',
                category: 'sport'
            },
            {
                title: 'CAT',
                category: 'sport'
            },
            {
                title: 'SPORT',
                category: 'sport'
            },
            {
                title: 'ART',
                category: 'sport'
            },
            {
                title: 'PEOPLE',
                category: 'people'
            }, 
            {
                title: 'CAR',
                category: 'car'
            }]
        },
        filters: {
            categoryFilter: function (infoBlocs) {
                return this.wasClicked ? this.categories : {};
            },

            caseFilter: function () {
                if (this.wasClicked) {
                    return this.reverseArray();
                }
                return this.alphaSortByKey(this.categories, 'category');
            },

            reverse: function(value) {
                // slice to make a copy of array, then reverse the copy
                return value.slice().reverse();
            }
        },
        methods: {
            selectCategory: function(category) {
                //this.wasClicked =! this.wasClicked;
                //this.categories = this.alphaSortByKey(this.categories, 'category');
                // if (this.reverse) {
                //  this.categories = this.alphaSortByKey(this.categories, 'category');
                // }
                // else {
                //  this.categories = this.reverseArray();
                // }

                if (this.reverse) {
                    this.categories = this.alphaSortByKey(this.categories, 'category');
                    this.reverse = false;
                }
                else {
                    this.categories = this.reverseArray();
                    //this.reverse = true;
                }
            },

            alphaSortByKey: function (arr, key) {
                arr.sort(function (a, b) {
                    if (a[key] < b[key])
                            return -1;
                    if (a[key] > b[key])
                            return 1;
                    return 0;
                });
                return arr;
            },

            reverseArray: function () {
                return this.categories.reverse();
            },

            changeOrder: function (event) {
              var self = this;
              self.reverse = self.reverse * -1
              var newItems = self.categories.slice().sort(function (a, b) { 
                var result;
                if (a.name < b.name) {
                  result = 1
                }
                else if (a.name > b.name) {
                  result = -1
                }
                else {
                  result = 0
                }
                return result * self.reverse
              })
              newItems.forEach(function (item, index) {
                item.position = index;
              });

              this.categories = newItems;
            }
        } 
    });


    </script>

{% endblock %}

3 个答案:

答案 0 :(得分:3)

这是一个工作功能的小提琴,用于排序和反转数组的顺序。对于反向我只使用内置的reverse()Javascript函数。对于字母数字排序,我借用了这个答案的解决方案:https://stackoverflow.com/a/4340339/6913895

https://jsfiddle.net/n1tbmgo9/

HTML:

<div id="wrap">
    <h2>Select a category</h2>
    <button @click="sort">
    Sort alphanumeric
    </button>
    <button @click="reverse">
    Reverse list
    </button>
    <ul id="categorySelect">
        <li v-for="cat in categories">${cat.title}</li>
    </ul>
</div>

使用Javascript:

Vue.config.delimiters = ['${', '}'];

new Vue({
  el: '#wrap',
  data: {
    selectedCategory: null,
    categories: [{
      title: 'ALL',
      category: null
    }, 
    {
      title: 'CATE',
      category: 'sport'
    }, 
    {
      title: 'DOG',
      category: 'sport'
    },
    {
      title: 'SPEED',
      category: 'sport'
    },
    {
      title: 'CAT',
      category: 'sport'
    },
    {
      title: 'SPORT',
      category: 'sport'
    },
    {
      title: 'ART',
      category: 'sport'
    },
    {
      title: 'PEOPLE',
      category: 'people'
    }, 
    {
      title: 'CAR',
      category: 'car'
    }]
  },
  methods: {
    sort: function () {
        this.categories.sort(this.sortAlphaNum);
    },
    reverse: function () {
        this.categories.reverse();
    },
    sortAlphaNum: function (a,b) {
      var reA = /[^a-zA-Z]/g;
      var reN = /[^0-9]/g;
      var aA = a.title.replace(reA, "");
      var bA = b.title.replace(reA, "");
      if(aA === bA) {
          var aN = parseInt(a.title.replace(reN, ""), 10);
          var bN = parseInt(b.title.replace(reN, ""), 10);
          return aN === bN ? 0 : aN > bN ? 1 : -1;
      } else {
          return aA > bA ? 1 : -1;
      }
    }
  }
});

内置的reverse()函数非常简单,因此我将详细介绍sortAlphaNum()排序函数。该函数被传递到sort()函数,并且必须返回1,0或-1,以指示传入的对象是否应该在数组中的特定方向上移动。

变量reAreN是正则表达式,分别用于标识字母和数字字符。

首先,该函数从传入的两个对象的标题中删除所有字母字符,并将它们进行相等性比较 var aA = a.title.replace(reA, "");var bA = b.title.replace(reA, "");

如果它们不相等则意味着我们有字母字符(而不仅仅是数字输入),我们可以相应地对它们进行排序。 return aA > bA ? 1 : -1;

如果剥离字母字符的标题相等(if(aA === bA)),则我们从对象标题中删除数字(保留非数字字符)。 var aN = parseInt(a.title.replace(reN, ""), 10); var bN = parseInt(b.title.replace(reN, ""), 10);

然后我们比较结果变量并返回适当的排序值(1,0,-1)。 return aN === bN ? 0 : aN > bN ? 1 : -1;

答案 1 :(得分:0)

创建一个计算属性,您可以手动对其进行排序,然后为其循环而不是数据prop

答案 2 :(得分:0)

有我的 List Component 实现和客户端订单实现:

<template>
  <div>
    <table class="table table-bordered" v-if="data.length">
      <thead>
        <tr>
          <th v-for="(colValue, colKey) in cols" :key="colKey">
            <a @click="sort(colKey)" href="javascript:void(0)">
              {{colValue}}
              <icon :name="(sortColumn === colKey) ? (sortAsc ? 'sort-down' : 'sort-up') : 'sort'"></icon>
            </a>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="row in data" :key="row.id">
          <td v-for="(colValue, colKey) in cols" :key="row.id + colKey">{{row[colKey]}}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import _ from 'lodash';
import apiServer from '@/utils/apiServer'; // 

export default {
  name: 'List',

  data() {
    return {
      data: [],
      sortColumn: '',
      sortAsc: true
    };
  },

  props: {
    cols: {
      type: Object,
      required: true
    },
    apiEndpoint: {
      type: String,
      required: true
    }
  }

  created() {
    this.fetchData();
  },

  watch: {
    '$route': 'fetchData'
  },

  methods: {
    async fetchData() {
      const response = await apiServer.get(this.apiEndpoint);
      this.data = response.data;
    },

    sort(colKey) {
      this.data = _.sortBy(this.data, [colKey]);

      if (this.sortColumn === colKey) {
        if (!this.sortAsc) {
          this.data = _.reverse(this.data);
        }

        this.sortAsc = !this.sortAsc;
      } else {
        this.sortAsc = false;
      }

      this.sortColumn = colKey;
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>

用法示例

<template>
  <div>
    <h1>Orders</h1>

    <List :cols="cols" api-endpoint="/orders" title="Orders" />
  </div>
</template>

<script>
import List from '@/components/List.vue';

export default {
  name: 'OrderList',
  components: { List },

  data() {
    return {
      cols: {
        id: 'Id',
        title: 'Title',
        created_at: 'Created at'
      }
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>