preface

Data-driven tables reduce tedious code.

code

Props part

    tableColumn: {
      type: Array.default: () = >[{label: "Serial number".align: "center".width: 50.type: "index"}, {prop: "name".label: "Name".align: "center"}, {prop: "age".label: "Age".align: "center"}, {prop: "sex".label: "Gender".align: "center",}]},tableData: {
      type: Array.default: () = >[{name: "Slippers in your face.".age: 18.sex: "Male",}]},size: {
      type: String.default: "medium",},stripe: {
      type: Boolean.default: false,},border: {
      type: Boolean.default: false,},fit: {
      type: Boolean.default: true,},showHeader: {
      type: Boolean.default: true,},headerCellStyle: {
      type: Function.default: (/*{ row, column, rowIndex, columnIndex }*/) = > {
        return { color: "# 000"}; }},cellStyle: {
      type: Function.default: (/** {row, column, rowIndex, columnIndex}*/) = > {
        return { color: "# 333"}; }},pagination: {
      type: Object.default: () = > ({
        current: 1.size: 10.total: 0,})},pageSizes: {
      type: Array.default: () = > [10.20.30.50],},Copy the code

Render part

  render(h) {
    const {
      tableData,
      size,
      stripe,
      border,
      fit,
      showHeader,
      headerCellStyle,
      cellStyle,
      sortChange,
      select,
      selectAll,
      selectionChange,
      tableColumn,
      / / paging
      pagination: { current, size: pageSize, total },
      pageSizes,
      sizeChange,
      currentChange,
    } = this;
    return h(
      "div",
      {
        class: {
          "render-table": true,
        },
      },
      [
        h(
          "el-table",
          {
            props: {
              data: tableData,
              size: size,
              stripe: stripe,
              border: border,
              fit: fit,
              "show-header": showHeader,
              "header-cell-style": headerCellStyle,
              "cell-style": cellStyle,
            },
            on: {
              "sort-change": sortChange,
              select: select,
              "select-all": selectAll,
              "selection-change": selectionChange,
            },
            style: {
              width: "100%",}},this.renderColumn(tableColumn, h)
        ),
        h("el-pagination", {
          props: {
            "current-page": current,
            "page-size": pageSize,
            "page-sizes": pageSizes,
            total: total,
            layout: "total, sizes, prev, pager, next, jumper",},on: {
            "size-change": sizeChange,
            "current-change": currentChange,
          },
          style: {
            "text-align": "right"."margin-top": "10px",},}),]); }Copy the code

The methods of

    createColumn(column) {
      return [
        "el-table-column",
        {
          props: {
            ...this.attributesColumn(column),
          },
        },
      ];
    },
    createScopedSlot({ scopedSlots, prop }, h) {
      let { tag, text, textStyle, click, slot } = scopedSlots;
      let { isTrue, isFunc, columnClick, scopedSlotText } = this;
      return {
        scopedSlots: {
          default: (props) = > {
            const value = props["row"][prop];
            if (slot) {
              return h(
                "div".this.$scopedSlots["opration"] ({row: props["row"]})); }return h(
              tag,
              {
                on: isTrue(click) ? { click: columnClick(props) } : {},
                style:
                  isFunc(textStyle) &&
                  textStyle(props["$index"] + 1, value, props["row"]), }, scopedSlotText(text, value, props) ); ,}}}; },renderColumn(columns, h) {
      if(! columns || ! columns.length) {return;
      }
      let tableColumn = [];
      columns.forEach((item) = > {
        let { scopedSlots } = item;
        let column = this.createColumn(item);
        let vNode;
        if (this.notEmpty(scopedSlots)) {
          column[1] = {
            ...column[1],... this.createScopedSlot(item, h), }; vNode = h(... column); }else{ vNode = h(... column,this.renderColumn(item.children, h));
        }
        tableColumn.push(vNode);
      });
      return tableColumn;
    },
    attributesColumn(column) {
      const attr = [
        "type"."label"."prop"."width"."align"."fixed"."sortable"."scopedSlots",];let obj = {};
      attr.forEach((prop) = > {
        column[prop] && (obj[prop] = column[prop]);
      });
      return obj;
    },
    notEmpty(obj) {
      if (typeof obj === "object" && JSON.stringify(obj) ! = ="{}") {
        return true;
      }
      return false;
    },
    isTrue(v) {
      return v === true;
    },
    isDef(v) {
      return v === undefined;
    },
    isFunc(v) {
      return typeof v === "function";
    },
    scopedSlotText(text, value, column) {
      const { $index: index, row } = column;
      if (!this.isDef(text)) {
        return this.isFunc(text) ? text(index, value, row) : text;
      }
      return value;
    },
    // Custom column click
    columnClick(scope) {
      let { $index, row } = scope;
      return () = > {
        this.$emit("columnClick", {
          index: $index, ... row, }); }; },// This event is triggered when the table's sorting criteria change
    sortChange({ order, prop }) {
      this.$emit("sortChange", { order, prop });
    },
    // The event that is triggered when the user manually checks the Checkbox of a data row
    select(selection, row) {
      this.$emit("select", selection, row);
    },
    // This event is triggered when the user manually checks all checkboxes
    selectAll(selection) {
      this.$emit("select-all", selection);
    },
    // This event is triggered when the selection changes
    selectionChange(selection) {
      this.$emit("selection-change", selection);
    },
    // When pageSize changes
    sizeChange(size) {
      this.$emit("pagination-change", {
        current: this.pagination.current,
        size,
      });
    },
    // When currentPage changes
    currentChange(current) {
      this.$emit("pagination-change", {
        current,
        size:this.pagination.size,
      });
    },
Copy the code

usage

Basic usage

<render-table />
Copy the code

The effect

    <render-table
      :border="true"
      :tableColumn="tableColumn"
      :tableData="tableData"
    />
    tableColumn: [
        {
          label: "Serial number".type: "index".width: 50.align: "center"}, {label: "Students".prop: "student".align: "center"}, {label: "Mathematics".align: "center".prop: "math"}, {label: "Chinese".align: "center".prop: "language"}, {label: "English".prop: "english".align: "center"],},tableData: [{student: "Zhang".math: 60.language: 60.english: 60}, {student: "Fifty".math: 66.language: 80.english: 77],},Copy the code

Pass data to the table by setting tableColumn, tableData properties.

The effect

multi-select

    <render-table
      :border="true"
      :tableColumn="tableColumn"
      :tableData="tableData"
      @select='select'
      @select-all='selectAll'
      @selection-change='selectionChange'/ > {// label:
      type: "selection".width: 50.align: "center",},Copy the code

To implement multiple selection, simply set the type property value to Selection. Methods such as SELECT, select-all, and selection-change are also provided. The usage is the same as that of el-table.

The effect

Header nesting is supported

        {
          label: "Performance".align: "center".children: [{label: "Mathematics".align: "center".prop: "math"}, {label: "Chinese".align: "center".prop: "language"}, {label: "English".prop: "english".align: "center",}]},Copy the code

To implement header nesting, add the children attribute to tableColumn.

The effect

Support for custom columns

        {
          label: "Students".prop: "student".align: "center".scopedSlots: {tag:'span'.text:'Custom'}},Copy the code

To implement custom columns you need to add scopedSlots and set tag and text. In the command, tag and text are user-defined display text. Text can be a string or a function

When text is a function

        {
          label: "Students".prop: "student".align: "center".scopedSlots: {tag:'span'.text:(index,value,row) = >{
              returnvalue; }}},Copy the code

The effect

If you need to set a style, you have textStyle

     {
          label: "Students".prop: "student".align: "center".scopedSlots: {tag:'span'.text:(index,value,row) = >{
              return value;
            },
            textStyle:(index,value,row) = >{
              return {color:'red'}}}},Copy the code

The effect

Need to listen for click callbacks, columnClick.

        <render-table
          :border="true"
          :tableColumn="tableColumn"
          :tableData="tableData"
          @select="select"
          @select-all="selectAll"
          @selection-change="selectionChange"
          @columnClick="columnClick"/ > {label: "Students".prop: "student".align: "center".scopedSlots: {tag:'span'.text:(index,value,row) = >{
              return value;
            },
            textStyle:(index,value,row) = >{
              return {color:'red'}},click:true}},columnClick(row) {
          console.log(row);
        },
Copy the code

In general, table clicks are about actions, like editing, you can do that.

        {
          label:'operation'.align:'center'.scopedSlots: {tag:'el-button'.click:true.text:'edit'}}Copy the code

The effect

It doesn’t feel like a lot to get here, but there are still some problems operating here. If you only use tag+text+click, you can’t do some complex operations, such as edit, delete, view, etc. That’s where the slot property comes in.

    <render-table
      :border="true"
      :tableColumn="tableColumn"
      :tableData="tableData"
      @select="select"
      @select-all="selectAll"
      @selection-change="selectionChange"
      @columnClick="columnClick"
    >
    <template #opration='{row}'>
      <el-button @click="edit(row)">The editor</el-button>
      <el-button>To view</el-button>
      <el-button>delete</el-button>
    </template>
    </render-table>
    
    {
      label:'operation'.align:'center'.scopedSlots: {slot:true}}Copy the code

The effect

attribute

The same usage as el-table is not specified.

table

          data: tableData,
          size: size,
          stripe: stripe,
          border: border,
          fit: fit,
          "show-header": showHeader,
          "header-cell-style": headerCellStyle,
          "cell-style": cellStyle,
          
Copy the code

column

        "type"."label"."prop"."width"."align"."fixed"."sortable"."scopedSlots".Copy the code

scopedSlots

Tag: Specifies the element tag. This parameter is mandatory if customization is required. Text: Custom text rendering, which can be string/function.functionThree parameters will be receivedindex.value.row
        textStyle: Custom stylefunctionReceive three parametersindex.value.row, the return valueobject
        click: Whether you need to click,true/false
        slot: Open the slot,true/false
Copy the code

pagination

            "current-page": current,
            "page-size": pageSize,
            "page-sizes": pageSizes,
            total: total,
Copy the code

The event

    columnClick(row)  // Custom click callback
    // The same as el-tableSortChange, Select, selectAll, selectionChange// Paging callback
    pagination-change({current,size})
Copy the code