网站首页 » 前端开发 » Vue » Vue2 组件:表格
上一篇:
下一篇:

Vue2 组件:表格

表格在很多列表页中很常见,所以我们有必要把它封装成一个组件。

这个组件实现了:

  • 表格标题对齐方式(alignTitle)及宽度可设置(width),可单独设置某个标题居中(align)
  • 自定义字段排序(指定哪些列有排序功能)
  • 大范围点击及精确点击都可触发

效果:

Vue2 表格组件

代码
<template>
<div class="table-box" :class="tableClass">
  <table>
    <thead :class="alignTitle">
      <tr>
        <th v-for="(item,index) in tableHeader" :key="index" @click="sort(item,$event)" :width="item.width">
          <div class="title-inner" :class="item.align" :current-sort="item.currentSort">
              {{item.name}}
              <span class="arrow" v-if="item.sort">
                <i class="asc" type="1" title="升序"></i>
                <i class="desc" type="-1" title="降序"></i>
              </span>
          </div>
        </th>
      </tr>
    </thead>
    <tbody>
      <slot name="tbody"></slot>
    </tbody>
  </table>
  </div>
</template>
<script>
/**
 * 表格实现了:
 * 表格标题对齐方式(alignTitle)及宽度可设置(width),可单独设置某个标题居中(align)
 * 自定义字段排序(指定哪些列有排序功能)
 * 大范围点击及精确点击都可触发
 */
export default {
  name: "Table",
  data() {
    return {
      lastSortItem: null
    };
  },
  props: {
    tableHeader: {
      type: Array,
      default: []
    },
    tableBody: {
      type: Array,
      default: []
    },
    // 默认按哪一列作为默认排序(从 0 开始)
    defaultSort: {
      type: Number,
      default: 0
    },
    alignTitle: {
      type: String,
      default: ""
    },
    tableClass: {
      // 自定义表格类,方便自定义样式
      type: String,
      default: ""
    }
  },
  created() {
    this.setSort(this.defaultSort);
  },
  methods: {
    sort(item, event) {
      if (!item.sort) {
        return;
      }
      const target = event.target; // 点击的元素对象
      // 如果点击的不是自己,清掉旧的
      if (item !== this.lastSortItem) {
        this.lastSortItem.currentSort = 0;
      }
      // 如果点击的是箭头
      if (target.nodeName.toLowerCase() === "i") {
        item.currentSort = target.getAttribute("type") * 1;
      } else {
        item.currentSort = !item.currentSort
          ? -1
          : item.currentSort === -1 ? 1 : 0;
        if (item !== this.tableHeader[0] && item.currentSort === 0) {
          // 如果点击其它列切换到 0 时,使用第一列作为默认排序
          this.setSort(0);
          return;
        }
      }
      // 保存当前排序的项
      this.lastSortItem = item;
      this.sortData(item);
    },
    // 数据排序
    sortData(item) {
      const key = item.key;
      const type = Object.prototype.toString;
      this.tableBody.sort(function(a, b) {
        const aKey = a[key];
        const bKey = b[key];
        if (
          type.call(a[key]) === "[object Number]" &&
          type.call(b[key]) === "[object Number]"
        ) {
          // 如果两个都是数字
          return (a[key] - b[key]) * item.currentSort;
        } else {
          // 如果是非数字(字母或汉字等)
          return a[key].localeCompare(b[key]) * item.currentSort;
        }
      });
    },
    // 设置根据哪一列进行排序
    setSort(index) {
      this.tableHeader[index].currentSort = 1;
      this.lastSortItem = this.tableHeader[index];
      this.sortData(this.lastSortItem);
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.table-box table {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
  border: 0;
}
.table-box table thead tr th,
.table-box table tbody tr td {
  border: 1px solid #e6e6e6;
  padding: 6px 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  box-sizing: border-box;
}
.table-box table thead tr th span.arrow {
  position: relative;
  display: inline-block;
  height: 28px;
  margin-left: 5px;
  width: 12px;
}
.table-box table thead tr th i {
  position: absolute;
  left: 0;
  width: 0;
  height: 0;
  cursor: pointer;
  border: 5px solid transparent;
}
.table-box table thead tr th i.desc {
  border-top-color: #b2b2b2;
  bottom: 2px;
}
.table-box table thead tr th i.asc {
  border-bottom-color: #b2b2b2;
  top: 2px;
}
.table-box table thead tr {
  background: #f2f2f2;
  user-select: none;
}
.table-box table thead .title-inner {
  display: flex;
  align-items: center;
  justify-content: center;
}
.table-box table thead.left .title-inner {
  justify-content: flex-start;
}
.table-box table thead.left .title-inner.center {
  justify-content: center;
}
.table-box table thead .title-inner[current-sort="1"] i.asc {
  border-bottom-color: #333;
}
.table-box table thead .title-inner[current-sort="-1"] i.desc {
  border-top-color: #333;
}
.table-box table tbody tr {
  transition: 0.3s;
}
.table-box table tbody tr:hover {
  background-color: #f2f2f2;
}
</style>

用法:

属性 详细说明
tableHeader 必填,表头数据
tableBody 必填,表格数据
defaultSort 可选 ,指定某列作为默认排序(默认值为0)
alignTitle 可选 ,标题对齐方式,默认居中
tableClass 可选 ,给 table-box 指定类,方便自定义样式

如果觉得这个表格还有什么需要完善的可以留言。

文章关键词:
  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/vue-components-table/

发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论 END