Vue + TS封装全局表格组件

在Vue项目中,我们经常需要使用表格来展示数据。为了提高代码复用性和开发效率,我们可以封装一个全局表格组件,方便在各个页面中使用。本文将介绍如何使用Vue和TypeScript来实现这个全局表格组件。

功能需求

我们的全局表格组件需要具备以下功能:

  1. 可以接受表格数据作为组件的props
  2. 表格支持排序和分页功能
  3. 表格支持自定义列和操作按钮
  4. 表格支持多选和单选功能

实现思路

我们可以使用element-ui提供的Table组件来实现表格的排序和分页功能,使用slot来实现自定义列和操作按钮,使用v-model来实现多选和单选功能。在实现过程中,我们需要注意以下几点:

  1. 表格数据应该使用Prop的方式传递到组件中,而不是使用组件内部的数据来处理。
  2. 表格的分页和排序功能应该由父组件来控制,当分页或排序状态改变时,父组件应该更新数据并传递给表格组件。
  3. 多选和单选功能应该使用v-model来实现,以便父组件能够获取选中的数据。

代码实现

<template>
  <el-table
    :data="tableData"
    :height="height"
    :max-height="maxHeight"
    :stripe="stripe"
    :border="border"
    :fit="fit"
    :show-header="showHeader"
    :highlight-current-row="highlightCurrentRow"
    :row-class-name="rowClassName"
    :row-style="rowStyle"
    :cell-class-name="cellClassName"
    :cell-style="cellStyle"
    :header-row-class-name="headerRowClassName"
    :header-row-style="headerRowStyle"
    :header-cell-class-name="headerCellClassName"
    :header-cell-style="headerCellStyle"
    :row-key="rowKey"
    :empty-text="emptyText"
    :default-sort="defaultSort"
    :tooltip-effect="tooltipEffect"
    :tooltip-align="tooltipAlign"
    @sort-change="handleSortChange"
    @selection-change="handleSelectionChange">
    <slot></slot>
  </el-table>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Table } from 'element-ui';

@Component({
  components: { Table }
})
export default class GlobalTable extends Vue {
  @Prop({ required: true })
  private tableData!: any[]; // 表格数据

  @Prop({ default: 0 })
  private height!: number; // 表格高度

  @Prop({ default: 0 })
  private maxHeight!: number; // 表格最大高度

  @Prop({ default: false })
  private stripe!: boolean; // 是否为斑马纹表格

  @Prop({ default: false })
  private border!: boolean; // 是否带有边框

  @Prop({ default: true })
  private fit!: boolean; // 是否自动适应父元素宽度

  @Prop({ default: true })
  private showHeader!: boolean; // 是否显示表头

  @Prop({ default: false })
  private highlightCurrentRow!: boolean; // 是否高亮当前行

  @Prop({ default: '' })
  private rowClassName!: string; // 行的类名

  @Prop({ default: {} })
  private rowStyle!: object; // 行的样式

  @Prop({ default: '' })
  private cellClassName!: string; // 单元格的类名

  @Prop({ default: {} })
  private cellStyle!: object; // 单元格的样式

  @Prop({ default: '' })
  private headerRowClassName!: string; // 表头行的类名

  @Prop({ default: {} })
  private headerRowStyle!: object; // 表头行的样式

  @Prop({ default: '' })
  private headerCellClassName!: string; // 表头单元格的类名

  @Prop({ default: {} })
  private headerCellStyle!: object; // 表头单元格的样式

  @Prop({ default: '' })
  private rowKey!: string; // 行的key值

  @Prop({ default: '暂无数据' })
  private emptyText!: string; // 无数据时显示的文本

  @Prop({ default: {} })
  private defaultSort!: object; // 默认排序

  @Prop({ default: 'dark' })
  private tooltipEffect!: string; // tooltip主题

  @Prop({ default: 'bottom-start' })
  private tooltipAlign!: string; // tooltip对齐方式

  private handleSortChange(sort: any) {
    this.$emit('sort-change', sort);
  }

  private handleSelectionChange(selection: any) {
    this.$emit('selection-change', selection);
  }
}
</script>

使用方法

在使用全局表格组件时,只需要在需要使用表格的地方引用该组件即可。使用时需要传递表格数据和其他相关属性作为组件的props。

<template>
  <div>
    <global-table
      :table-data="tableData"
      :height="400"
      :max-height="500"
      :stripe="true"
      :border="true"
      :fit="true"
      :show-header="true"
      :highlight-current-row="true"
      :row-class-name="rowClassName"
      :row-style="rowStyle"
      :cell-class-name="cellClassName"
      :cell-style="cellStyle"
      :header-row-class-name="headerRowClassName"
      :header-row-style="headerRowStyle"
      :header-cell-class-name="headerCellClassName"
      :header-cell-style="headerCellStyle"
      :row-key="rowKey"
      :empty-text="emptyText"
      :default-sort="defaultSort"
      :tooltip-effect="tooltipEffect"
      :tooltip-align="tooltipAlign"
      @sort-change="handleSortChange"
      @selection-change="handleSelectionChange">
      <!-- 自定义列和操作按钮的slot -->
      <el-table-column prop="name" label="姓名"></el-table-column>
      <el-table-column prop="age" label="年龄"></el-table-column>
      <el-table-column prop="address" label="地址"></el-table-column>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button type="primary" size="small">编辑</el-button>
          <el-button type="danger" size="small">删除</el-button>
        </template>
      </el-table-column>
    </global-table>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import GlobalTable from '@/components/GlobalTable.vue';

@Component({
  components: { GlobalTable }
})
export default class App extends Vue {
  private tableData = [
    { name: '张三', age: 18, address: '上海市' },
    { name: '李四', age: 22, address: '北京市' },
    { name: '王五', age: 30, address: '广州市' },
  ];

  private rowClassName(row: any, index: number) {
    return index % 2 === 0 ? 'even-row' : 'odd-row';
  }

  private rowStyle(row: any, index: number) {
    return index % 2 === 0 ? { background: '#f4f4f4' } : {};
  }

  private cellClassName({ row, column, rowIndex, columnIndex }: any) {
    return row.name === '张三' ? 'special-cell' : '';
  }

  private cellStyle({ row, column, rowIndex, columnIndex }: any) {
    return row.name === '张三' ? { background: '#ffcccc' } : {};
  }

  private headerRowClassName(column: any, columnIndex: number) {
    return columnIndex === 0 ? 'first-column' : '';
  }

  private headerRowStyle(column: any, columnIndex: number) {
    return columnIndex === 0 ? { background: '#f2f2f2' } : {};
  }

  private headerCellClassName({ column, columnIndex }: any) {
    return column.label === '地址' ? 'special-header' : '';
  }

  private headerCellStyle({ column, columnIndex }: any) {
    return column.label === '地址' ? { background: '#ccffcc' } : {};
  }

  private rowKey(row: any) {
    return row.name;
  }

  private defaultSort = {
    prop: 'age',
    order: 'descending'
  };

  private tooltipEffect = 'light';

  private tooltipAlign = 'top-start';

  private handleSortChange(sort: any) {
    console.log(sort);
  }

  private handleSelectionChange(selection: any) {
    console.log(selection);
  }
}
</script>

总结

通过封装全局表格组件,我们可以大大提高代码复用性和开发效率。在实现过程中,我们需要注意将表格数据作为props传递到组件中,并且将分页和排序等状态控制在父组件中。同时,使用v-model来实现多选和单选功能,以便父组件能够获取选中的数据。希望本文能够对大家在Vue项目中封装全局组件有所帮助。

你可能感兴趣的:(vue.js,javascript,ecmascript)