如何使用vue.js对表中的日期进行排序

时间:2016-04-02 05:51:57

标签: javascript sorting date html-table vue.js

我的表格基于Vue.js中的网格组件示例。网站

我在表格中排序日期时遇到问题。我从服务器端获取所有表数据作为JSON。因此,在提供的代码中,我只是在 var mockDataFromServerSide 中模拟了数据。

以下是代码:https://jsfiddle.net/5w1wzhvw/3/

HTML文件:

<!-- component template -->
<script type="text/x-template" id="grid-template">
  <table>
    <thead>
      <tr>
        <th v-for="key in columns"
          v-on:click="sortBy(key)"
          :class="{active: sortKey == key}">
          {{key | capitalize}}
          <span class="arrow"
            :class="sortOrders[key] > 0 ? 'asc' : 'dsc'">
          </span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="
        entry in data
        | filterBy filterKey
        | orderBy sortKey sortOrders[sortKey]">
        <td v-for="key in columns">
          {{entry[key]}}
        </td>
      </tr>
    </tbody>
  </table>
</script>

<!-- demo root element -->
<div id="demo">
  <form id="search">
    Search <input name="query" v-model="searchQuery">
  </form>
  <demo-grid
    :filter-key="searchQuery">
  </demo-grid>
</div>

Js文件:

var gridColumns = ['name', 'date'];
var mockDataFromServerSide = [
      { name: 'Chuck Norris', date: "01 Dec 2016" },
      { name: 'Bruce Lee', date: "23 Apr 2005" },
      { name: 'Jackie C', date: "30 Jan 2012" },
      { name: 'Jet Li', date: "20 Apr 2006" }
    ];
// register the grid component
Vue.component('demo-grid', {
  template: '#grid-template',
  props: {
        filterKey: String
  },
  data: function () {
    var sortOrders = {}
    gridColumns.forEach(function (key) {
      sortOrders[key] = 1
    })
    return {
      sortKey: '',
      sortOrders: sortOrders,
      columns: gridColumns,
      data: mockDataFromServerSide
    }
  },
  methods: {
    sortBy: function (key) {
      this.sortKey = key
      this.sortOrders[key] = this.sortOrders[key] * -1
    }
  }
})

// bootstrap the demo
var demo = new Vue({
  el: '#demo',
  data: {
    searchQuery: ''
  }
})

我还尝试在日期中添加过滤器。排序正确但显示的日期显示为&#34; 2016年4月2日星期四00:00:00 GMT + 0800(中国标准时间)&#34;。我希望日期显示为 2016年4月2日

添加了过滤器代码:https://jsfiddle.net/kr1m5de5/1/

HTML文件(添加过滤器):

<!-- component template -->
<script type="text/x-template" id="grid-template">
  <table>
    <thead>
      <tr>
        <th v-for="key in columns"
          v-on:click="sortBy(key)"
          :class="{active: sortKey == key}">
          {{key | capitalize}}
          <span class="arrow"
            :class="sortOrders[key] > 0 ? 'asc' : 'dsc'">
          </span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="
        entry in data
        | filterBy filterKey
        | orderBy sortKey sortOrders[sortKey]
        | datesFilter">
        <td v-for="key in columns">
          {{entry[key]}}
        </td>
      </tr>
    </tbody>
  </table>
</script>

<!-- demo root element -->
<div id="demo">
  <form id="search">
    Search <input name="query" v-model="searchQuery">
  </form>
  <demo-grid
    :filter-key="searchQuery">
  </demo-grid>
</div>

JS文件(添加过滤器):

var gridColumns = ['name', 'date'];

var mockDataFromServerSide = [
      { name: 'Chuck Norris', date: "01 Dec 2016" },
      { name: 'Bruce Lee', date: "23 Apr 2005" },
      { name: 'Jackie C', date: "30 Jan 2012" },
      { name: 'Jet Li', date: "20 Apr 2006" }
    ];
// register the grid component
Vue.component('demo-grid', {
  template: '#grid-template',
  props: {
        filterKey: String
  },
  filters: {
    datesFilter: function (data) {
      data.forEach(function (row) {
        row.date = new Date(row.date);
      });
      return data;
        }
    },
  data: function () {
    var sortOrders = {}
    gridColumns.forEach(function (key) {
      sortOrders[key] = 1
    })
    return {
      sortKey: '',
      sortOrders: sortOrders,
      columns: gridColumns,
      data: mockDataFromServerSide
    }
  },
  methods: {
    sortBy: function (key) {
      this.sortKey = key
      this.sortOrders[key] = this.sortOrders[key] * -1
    }
  }
})

// bootstrap the demo
var demo = new Vue({
  el: '#demo',
  data: {
    searchQuery: ''
  }
})

请让我知道如何解决它或者是否有更好的方法来解决它。

1 个答案:

答案 0 :(得分:0)

我通过制作一个TableHeader组件解决了这个问题,该组件说语义原因,我使用了语义UI。对于代码中的西班牙文感到抱歉,无论如何必须承认。另外,此代码也可以使用,但是如果您看到对代码/答案的改进,请告诉我!

如您所见,我真的不在前面排序...我对排序后的项目提出了新的要求。

<template>
    <th @click="cycleSort(sth, $event)">
        <span><span>{{ sth.texto }}&nbsp;&nbsp;</span><i class="icon" :class="sth.icon"></i><sub v-if="sth.posicion > 0"><small>{{ sth.posicion }}</small></sub></span>
    </th>
</template>
<script>
export default {
  name: "SemanticTableHeader",
  props: {
      sth : {
          type : Object,
          default: () => {}
      },
      sths : {
          type : Array,
          default: () => { return [] }
      },
      filtrosOrder : {
          type : Array,
          default: () => { return [] }
      },
      isSearching : {
          type : Boolean,
          required : true
      }
  },
  methods: {
      cycleSort(sth, event) {

          if(this.isSearching == true){
              return false;
          }

          switch (sth.direction) {
              case null:
              sth.direction = 'asc';
              sth.icon = 'sort ascending';
              break;

              case 'asc':
              sth.direction = 'desc';
              sth.icon = 'sort descending';
              break;

              case 'desc':
              sth.direction = null;
              sth.icon = 'sort disabled';
              break;

              default:
              sth.direction = null;
              sth.icon = 'sort disabled';
          }

        this.manejaCambioHeader(sth);

      },
      manejaCambioHeader: _.debounce(function (sth) {
          var self = this;

          console.log(this.filtrosOrder);

          let auxUser = _.find(this.filtrosOrder, function(o) { return o.id == sth.id; });

          if( auxUser != null ){

              auxUser.direction = sth.direction;

              if(auxUser.direction == null){
                  for (var i=0 ; i < this.filtrosOrder.length ; i++){
                      if (this.filtrosOrder[i].id === auxUser.id) {

                          let auxSths =  _.find(self.sths, function(o) { return o.id == sth.id; });
                          auxSths.posicion = 0;

                          this.filtrosOrder.splice(i, 1);
                      }
                  }
              }
          }else{
              this.filtrosOrder.push({ id: sth.id, direction: sth.direction });
          }

          for (var i=0 ; i < self.filtrosOrder.length; i++){
              let auxSths =  _.find(this.sths, function(o) { return o.id == self.filtrosOrder[i].id; });

              auxSths.posicion = i + 1;
          }

          console.log(this.filtrosOrder);

          this.$emit('sortHeaderChanged', sth);

    }, 400),
  },
}
</script>
<style lang="css" scoped>
th span{
    cursor: pointer !important;
    -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
    -khtml-user-select: none; /* Konqueror HTML */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* Internet Explorer/Edge */
    user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */
}

i.icon{
    margin: 0em -0.2em 0em 0em;
}
</style>

在我的索引视图中,我只是加载组件并像这样使用它

<template>
    <table>
        <thead>
            <tr>
                <semantic-table-header v-for="sth in sths" :key="sth.key"
                :sth="sth"
                :sths="sths"
                :isSearching="isSearching"
                :filtrosOrder="filtros.orderBy"
                @sortHeaderChanged="fetchIndex"
                ></semantic-table-header>
                <th></th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="contact in contacts" :key="contact.key" :class="[contact.justAdded ? 'justAdded' : '']">
            </tr>
        </tbody>
    </table>
</template>

export default {
    name: "ContactsIndex",
    data:() => ({
        filtros:{
            orderBy:[
                {   id: 'nombre',   direction: 'asc'    } // orderBy is calculated through the headers component
            ]
        },
        sths:[
            {   id: 'nombre',       texto: 'Nombre',                icon: 'sort ascending',     direction: 'asc',   posicion: 1 },
            {   id: 'telefonos',    texto: 'Teléfono(s)',           icon: 'sort disabled',      direction: null,    posicion: 0 },
            {   id: 'emails',       texto: 'Correo Electrónico(s)', icon: 'sort disabled',      direction: null,    posicion: 0 },
            {   id: 'estatus',      texto: 'Estatus',               icon: 'sort disabled',      direction: null,    posicion: 0 }
        ],
        contacts: [],
    }),
    created() {
        this.fetchIndex();
    },
    methods: {
        resetFilters() {
            // this function is to reset filters and headers
            Object.assign(this.$data.filtros, this.$options.data().filtros);
            this.$data.sths =  this.$options.data().sths;
            this.fetchIndex();
        },
        fetchIndex() {
            let self = this;

            // this is a wrapper i made for an axios post call you can replace it with a normal call
            singleIndexRequest('/api/v1/contacts/index', self).then(response => {
                self.contacts = response.data.contacts;
            });
        },
    }
}