Vue + TS encapsulates the global table component

In Vue projects, we often need to use tables to display data. In order to improve code reusability and development efficiency, we can encapsulate a global table component for easy use in each page. This article will introduce how to use Vue and TypeScript to implement this global table component.

Functional Requirements

Our global table component needs to have the following functionality:

  1. Can accept tabular data as props of components
  2. The table supports sorting and paging functions
  3. Tables support custom columns and action buttons
  4. Table supports multiple selection and single selection functions

Implementation ideas

We can use the Table component provided by element-ui to implement table sorting and paging functions, use slots to implement custom columns and operation buttons, and use v-model to implement multi-selection and single-selection functions. In the implementation process, we need to pay attention to the following points:

  1. Table data should be passed to the component using Prop, rather than using the data inside the component for processing.
  2. The paging and sorting functions of the table should be controlled by the parent component. When the paging or sorting status changes, the parent component should update the data and pass it to the table component.
  3. Multi-selection and single-selection functions should be implemented using v-model so that the parent component can get the selected data.

Code

<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>

Instructions

When using the global table component, you only need to reference the component where the table needs to be used. When using it, you need to pass the table data and other related properties as props of the component.

<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>

Summarize

By encapsulating the global table component, we can greatly improve code reusability and development efficiency. In the implementation process, we need to pay attention to passing the table data into the component as props, and controlling the state of paging and sorting in the parent component. At the same time, use v-model to implement multi-selection and single-selection functions, so that the parent component can obtain the selected data. I hope this article can help you encapsulate global components in Vue projects.

Guess you like

Origin blog.csdn.net/qq_27244301/article/details/131474656