vue 使用render 动态创建element ui table 增强版

 table 参数说明

  /**
   * 属性参数
   * @property {Array} [tableData = []] data table表格数据
   * @property {Array} [tableHeader = []] data table头部内容
   * @property {Object} [defaultName = { lable: "lable",prop: "prop",icon: "icon", width: "width",type: "type",tag: "tag",tableColumnAttributes: "tableColumnAttributes" }] defaultName 指引查找参数 icon用于表示该列是显示图片目前功能求实现
   * @property {Function} cellClick   当某个单元格被点击时会触发该事件  row, column, cell, event
   * @property {Function} select 当用户手动勾选数据行的 Checkbox 时触发的事件  selection, row
   * @property {Function} selectAll 当用户手动勾选全选 Checkbox 时触发的事件 selection
   * @property {Function} selectionChange 当选择项发生变化时会触发该事件 selection
   * @property {Function} cellMouseEnter 当单元格 hover 进入时会触发该事件 row, column, cell, event
   * @property {Function} cellMouseLeave 当单元格 hover 退出时会触发该事件 row, column, cell, event
   * @property {Function} celldblClick  当某个单元格被双击击时会触发该事件 row, column, cell, event
   * @property {Function} rowClick 当某一行被点击时会触发该事件 row, column, event
   * @property {Function} rowContextMenu 当某一行被鼠标右键点击时会触发该事件 row, column, event
   * @property {Function} rowdblClick 当某一行被双击时会触发该事件  row, column, event
   * @property {Function} headerClick 当某一列的表头被点击时会触发该事件 column, event
   * @property {Function} headerContextMenu 当某一列的表头被鼠标右键点击时触发该事件  column, event
   * @property {Object} tableAttributes(Table Attributes) 参考 https://element.eleme.cn/#/zh-CN/component/table  (max-height 这种要写成maxHeight)
   * @property {Function} operationCallback 操作项回调 event, props
   * @property {Boolean} isPage 是否显示分页插件默认为false;当isPage 为true 时需要为pageAttributes配置参数
   * @property {Object} pageAttributes 对应element 分页的 Attributes参数中线间隔,要去中线并把中线连接首字母大写;如:current-page写成 currentPage
   * @property {Function} sizeChange pageSize 改变时会触发
   * @property {Function} currentChange currentPage 改变时会触发
   * @property {Function} prevClick 用户点击上一页按钮改变当前页后触发
   * @property {Function} nextClick 用户点击下一页按钮改变当前页后触发
   *  @property {Function} customColumnCallback 自定义table 列的内容(当tableHeader里面的type=="component"时才会有用) 返回 createElement, props, name三个值;createElement()是vue 里面的渲染函数,props 返回的是当前行的所有内容,name 是当前行绑定的显示属性主要用标识,从而实现不同的列使不同的定义
   */

新建一个createTable  js文件 然后内容如下

/**
 * 动态创建 table
 * @module my-table
 * @example
 * @author child
 * @date 2020-10-15 11:19:24
 * // 使用说明
 */
export default {
  name: "createTable",
  /**
   * 属性参数
   * @property {Array} [tableData = []] data table表格数据
   * @property {Array} [tableHeader = []] data table头部内容
   * @property {Object} [defaultName = { lable: "lable",prop: "prop",icon: "icon", width: "width",type: "type",tag: "tag",tableColumnAttributes: "tableColumnAttributes" }] defaultName 指引查找参数 icon用于表示该列是显示图片目前功能求实现
   * @property {Function} cellClick   当某个单元格被点击时会触发该事件  row, column, cell, event
   * @property {Function} select 当用户手动勾选数据行的 Checkbox 时触发的事件  selection, row
   * @property {Function} selectAll 当用户手动勾选全选 Checkbox 时触发的事件 selection
   * @property {Function} selectionChange 当选择项发生变化时会触发该事件 selection
   * @property {Function} cellMouseEnter 当单元格 hover 进入时会触发该事件 row, column, cell, event
   * @property {Function} cellMouseLeave 当单元格 hover 退出时会触发该事件 row, column, cell, event
   * @property {Function} celldblClick  当某个单元格被双击击时会触发该事件 row, column, cell, event
   * @property {Function} rowClick 当某一行被点击时会触发该事件 row, column, event
   * @property {Function} rowContextMenu 当某一行被鼠标右键点击时会触发该事件 row, column, event
   * @property {Function} rowdblClick 当某一行被双击时会触发该事件  row, column, event
   * @property {Function} headerClick 当某一列的表头被点击时会触发该事件 column, event
   * @property {Function} headerContextMenu 当某一列的表头被鼠标右键点击时触发该事件  column, event
   * @property {Object} tableAttributes(Table Attributes) 参考 https://element.eleme.cn/#/zh-CN/component/table  (max-height 这种要写成maxHeight)
   * @property {Function} operationCallback 操作项回调 event, props
   * @property {Boolean} isPage 是否显示分页插件默认为false;当isPage 为true 时需要为pageAttributes配置参数
   * @property {Object} pageAttributes 对应element 分页的 Attributes参数中线间隔,要去中线并把中线连接首字母大写;如:current-page写成 currentPage
   * @property {Function} sizeChange pageSize 改变时会触发
   * @property {Function} currentChange currentPage 改变时会触发
   * @property {Function} prevClick 用户点击上一页按钮改变当前页后触发
   * @property {Function} nextClick 用户点击下一页按钮改变当前页后触发
   * @property {Function} customColumnCallback 自定义table 列的内容(当tableHeader里面的type=="component"时才会有用) 返回 createElement, props, name三个值;createElement()是vue 里面的渲染函数,props 返回的是当前行的所有内容,name 是当前行绑定的显示属性主要用标识,从而实现不同的列使不同的定义
   */
  props: {
    // 数据字段名称映射
    defaultName: {
      type: Object,
      default() {
        return {
          lable: "lable",
          prop: "prop",
          icon: "icon",
          width: "width",
          type: "type",
          tag: "tag",
          tableColumnAttributes: "tableColumnAttributes"
        };
      }
    },
    tableData: {
      type: Array,
      default() {
        return [];
      }
    },
    tableHeader: {
      type: Array,
      default() {
        return [];
      }
    },
    cellClick: {
      type: Function,
      default: res => {
        return res;
      }
    },
    select: {
      type: Function,
      default: res => {
        return res;
      }
    },
    selectAll: {
      type: Function,
      default: res => {
        return res;
      }
    },
    selectionChange: {
      type: Function,
      default: res => {
        return res;
      }
    },
    cellMouseEnter: {
      type: Function,
      default: res => {
        return res;
      }
    },
    cellMouseLeave: {
      type: Function,
      default: res => {
        return res;
      }
    },
    celldblClick: {
      type: Function,
      default: res => {
        return res;
      }
    },
    rowClick: {
      type: Function,
      default: res => {
        return res;
      }
    },
    rowContextMenu: {
      type: Function,
      default: res => {
        return res;
      }
    },
    rowdblClick: {
      type: Function,
      default: res => {
        return res;
      }
    },
    headerClick: {
      type: Function,
      default: res => {
        return res;
      }
    },
    headerContextMenu: {
      type: Function,
      default: res => {
        return res;
      }
    },
    tableAttributes: {
      type: Object,
      default() {
        return {
          stripe: false,
          border: false
        };
      }
    },
    operationCallback: {
      type: Function,
      default: res => {
        return res;
      }
    },
    isPage: {
      type: Boolean,
      default() {
        return false;
      }
    },
    pageAttributes: {
      type: Object,
      default() {
        return {};
      }
    },
    sizeChange: {
      type: Function,
      default: res => {
        return res;
      }
    },
    currentChange: {
      type: Function,
      default: res => {
        return res;
      }
    },
    prevClick: {
      type: Function,
      default: res => {
        return res;
      }
    },
    nextClick: {
      type: Function,
      default: res => {
        return res;
      }
    },
    customColumnCallback: {
      type: Function,
      default: (createElement, props, name) => {
        return props.row[name];
      }
    }
  },
  methods: {
    grouping(array) {
      let groups = {
        default: []
      };
      let props = this.defaultName;
      array.forEach(n => {
        let key = n[props.group];
        if (key) {
          groups[key] = groups[key] || [];
          groups[key].push(n);
        } else {
          groups["default"].push(n);
        }
      });
      return groups;
    },
    createTableColumn(h, item) {
      let props = this.defaultName;
      return h("el-table-column", {
        props: {
          ...item[props.tableColumnAttributes],
          prop: item[props.prop],
          label: item[props.lable],
          width: item[props.width]
        }
      });
    },
    createTableColumnSelect(h, item) {
      let props = this.defaultName;
      return h("el-table-column", {
        props: {
          ...item[props.tableColumnAttributes],
          width: item[props.width],
          type: "selection"
        }
      });
    },
    createTableColumnOperation(h, item) {
      let props = this.defaultName;
      let tagItem = item[props.tag];
      let _this = this;
      return h("el-table-column", {
        props: {
          ...item[props.tableColumnAttributes],
          prop: item[props.prop],
          label: item[props.lable],
          width: item[props.width]
        },
        scopedSlots: {
          default: function(props) {
            let nodes = [];
            tagItem.forEach(items => {
              nodes.push(
                h(
                  items.tagType,
                  {
                    props: {
                      ...items.attributes
                    },
                    // on: {
                    //   click: event => {
                    //     _this.operationCallback(event, props, items.name);
                    //   }
                    // },
                    nativeOn: {
                      click: event => {
                        _this.operationCallback(event, props, items.name);
                      }
                    }
                  },
                  items.name
                )
              );
            });
            return nodes;
          }
        }
      });
    },
    createTableCustomColumnContent(h, item) {
      let props = this.defaultName;
      let _this = this;
      let columnName = item[props.prop];
      return h("el-table-column", {
        props: {
          ...item[props.tableColumnAttributes],
          prop: item[props.prop],
          label: item[props.lable],
          width: item[props.width]
        },
        scopedSlots: {
          default: function(prop) {
            return _this.customColumnCallback(h, prop, columnName);
          }
        }
      });
    },
    createNodes(h, array) {
      let nodes = [],
        groups = this.grouping(array);
      let props = this.defaultName;
      for (let key in groups) {
        let items = groups[key] || [];
        items.forEach(item => {
          //nodes.push(this.createTableComponent(h, item));
          if (item[props.type].toLowerCase() === "normal") {
            //创建数据列
            nodes.push(this.createTableColumn(h, item));
          } else if (item[props.type].toLowerCase() === "select") {
            //创建选择列
            nodes.push(this.createTableColumnSelect(h, item));
          } else if (item[props.type].toLowerCase() === "operation") {
            if (item[props.tag].length > 0 && item[props.tag] != undefined) {
              //创建操作列
              nodes.push(this.createTableColumnOperation(h, item));
            }
          } else if (item[props.type].toLowerCase() === "component") {
            nodes.push(this.createTableCustomColumnContent(h, item));
          }
        });
      }
      return nodes;
    }
  },
  render(h) {
    let table = h(
      "el-table",
      {
        props: {
          ...this.tableAttributes,
          data: this.tableData
        },
        nativeOn: {},
        class: "custom-table",
        on: {
          select: (selection, row) => {
            this.select(selection, row);
          },
          "select-all": selection => {
            this.selectAll(selection);
          },
          "selection-change": selection => {
            this.selectionChange(selection);
          },
          "cell-mouse-enter": (row, column, cell, event) => {
            this.cellMouseEnter(row, column, cell, event);
          },
          "cell-mouse-leave": (row, column, cell, event) => {
            this.cellMouseLeave(row, column, cell, event);
          },
          "cell-click": (row, column, cell, event) => {
            this.cellClick(row, column, cell, event);
          },
          "cell-dblclick": (row, column, cell, event) => {
            this.celldblClick(row, column, cell, event);
          },
          "row-click": (row, column, event) => {
            this.rowClick(row, column, event);
          },
          "row-contextmenu": (row, column, event) => {
            this.rowContextMenu(row, column, event);
          },
          "row-dblclick": (row, column, event) => {
            this.rowdblClick(row, column, event);
          },
          "header-click": (column, event) => {
            this.headerClick(column, event);
          },
          "header-contextmenu": (column, event) => {
            this.headerContextMenu(column, event);
          }
          // "sort-change": (selection, row) => {
          //   console.log(selection, row);
          // },
          // "filter-change": (selection, row) => {
          //   console.log(selection, row);
          // },
          // select: (selection, row) => {
          //   console.log(selection, row);
          // }
        },
        ref: "table"
      },
      this.createNodes(h, this.tableHeader)
    );
    if (this.isPage) {
      let _this = this;
      let page = h(
        "div",
        {
          class: ["page-div", "block"]
        },
        [
          h("el-pagination", {
            // 组件 prop
            props: {
              ...this.pageAttributes
            },
            on: {
              "size-change": function(param) {
                _this.sizeChange(param);
              },
              "current-change": function(param) {
                _this.currentChange(param);
              },
              "prev-click": function(param) {
                _this.prevClick(param);
              },
              "next-click": function(param) {
                _this.nextClick(param);
              }
            }
          })
        ]
      );
      return h("div", {}, [table, page]);
    }
    return h("div", {}, [table]);
  }
};
/**render(createElement){ return createElement('标签名','执行的操作','展示的内容') } */

然后创建table 表头及数据绑定文件 内容如下:

/***
 *  @property {Object} tableColumnAttributes 对应(Table-column Attributes) https://element.eleme.cn/#/zh-CN/component/table 但lable、prop、width参数除外
 *  @property {Array} tag [{name: "标签要显示的内容",tagType: "要创建什么标签",attributes: {size: "mini",type: "danger"}}]操作项要显示的标签操作(支持多标签并绑定点击回调) attributes 是element标签对应的东西
 *  @property {String} 数组中的 type 目前定义了四种类型 normal、operation、select、component 数据列、操作列、选择列、自定义列的内容
 */
module.exports = {
  test: [
    {
      lable: "站點",
      prop: "name",
      width: "80",
      type: "normal",
      tableColumnAttributes: {}
    },
    { lable: "站點編碼", prop: "date", type: "normal" },
    { lable: "綁定線路", prop: "address", type: "normal" },
    { lable: "站牌種類", prop: "1", type: "normal" },
    { lable: "佈局模式", prop: "1", type: "normal" },
    { lable: "重啟時間", prop: "1", type: "normal" },
    { lable: "同步時間", prop: "1", type: "normal" },
    { lable: "節目下載", prop: "1", type: "normal" },
    { lable: "截屏", prop: "1", type: "normal" },
    { lable: "刷新頻率", prop: "1", type: "normal" },
    { lable: "黑夜模式", prop: "1", type: "normal" },
    { lable: "狀態", prop: "1", type: "normal" },
    {
      lable: "詳情",
      prop: "1",
      type: "operation",
      tag: [
        {
          name: "删除",
          tagType: "el-button",
          attributes: {
            size: "mini",
            type: "danger"
          }
        }
      ]
    }
  ]
};

test 只是个名称自己定义有意义的名称就好


然后使用

<template>
  <section class="content">
    <el-row>
      <el-col :span="24"
        ><div class="grid-content bg-purple-dark">
          <createTable
            :tableData="tableData"
            :tableHeader="tableDataHeader"
            :tableAttributes="{
              stripe: true,
              border: true
            }"
            :operationCallback="sdf"
          >
          </createTable></div
      ></el-col>
    </el-row>
  </section>
</template>
<script>
import tableHeader from "../components/table/testTable.js"; 

export default {
  data() {
    return {
      tableData: [
        {
          date: "2016-05-02",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄",
          tempHtml: `<el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>`
        },
        {
          date: "2016-05-04",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1517 弄",
          tempHtml: `<el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>`
        },
        {
          date: "2016-05-01",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1519 弄",
          tempHtml: `<button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</button>`
        },
        {
          date: "2016-05-03",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1516 弄",
          tempHtml: `<el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>`
        }
      ],
      tableDataHeader: null
    };
  },
  created: function() {
    //绑定table 表头数据
    this.tableDataHeader = tableHeader.test;
  },
  methods: {
    sdf(event, props) {
     //操作回调
      console.log(event, props);
    }
  },
  components: {
  //引用自定义的组件
    createTable: resolve =>
      require(["../components/table/createTable.js"], resolve)
  }
};
</script>
<style scoped>
.content {
  box-sizing: border-box;
  padding: 15px;
}
</style>

效果:

image.png

自定义table 表头图标:

module.exports = {
  test: [
    {
      lable: "站點",
      prop: "name",
      width: "80",
      type: "normal",
      tableColumnAttributes: {
        renderHeader: (h, { column }) => {
          //这里测试在table 表头添加图标
          return h("div", [
            h("span", column.label),
            h("i", {
              class: "el-icon-location",
              style: "color:#409eff;margin-left:5px;"
            })
          ]);
        }
      }
    },
    { lable: "站點編碼", prop: "date", type: "normal" },
    { lable: "綁定線路", prop: "address", type: "normal" },
    { lable: "站牌種類", prop: "1", type: "normal" },
    { lable: "佈局模式", prop: "1", type: "normal" },
    { lable: "重啟時間", prop: "1", type: "normal" },
    { lable: "同步時間", prop: "1", type: "normal" },
    { lable: "節目下載", prop: "1", type: "normal" },
    { lable: "截屏", prop: "1", type: "normal" },
    { lable: "刷新頻率", prop: "1", type: "normal" },
    { lable: "黑夜模式", prop: "1", type: "normal" },
    { lable: "狀態", prop: "1", type: "normal" },
    {
      lable: "詳情",
      prop: "1",
      type: "operation",
      tag: [
        {
          name: "删除",
          tagType: "el-button",
          attributes: {
            size: "mini",
            type: "danger"
          }
        }
      ]
    }
  ]
};

效果:

image.png


启用分页代碼如下:

  <createTable
            :tableData="tableData"
            :tableHeader="tableDataHeader"
            :tableAttributes="{
              stripe: true,
              border: true
            }"
            :operationCallback="sdf"
            :isPage="true"
            :pageAttributes="{
              layout: 'prev, pager, next',
              total: 1000,
              background: true
            }"
          >
          </createTable>

效果:

image.png

此外还提供了一个非常强大的方法,可以让你对table列中的内容进行自由的定义实现在各种花样,但你需要对vue 的渲染函数(render)有一定的了解和使用

注意 tableHeader 里面的type为component时才会有效果

customColumnCallback(createElement, props, name) 自定义table 列的内容 返回 createElement, props, name三个值;createElement()是vue 里面的渲染函数,props 返回的是当前行的所有内容,name 是当前行绑定的显示属性主要用标识,从而实现不同的列使不同的定义

比如我要对数据的第一列实现a标签跳转:

首先定义一个方法内容如下:

    callback(createElement, props, name) {
      return [
        createElement(
          "a",
          {
            attrs: {
              href: "#"
            }
          },
          props.row[name]
        )
      ];
    }
  },

然后在组件中进行使用这个方法(callback):

 <createTable
            :tableData="tableData"
            :tableHeader="tableDataHeader"
            :tableAttributes="{
              stripe: true,
              border: true
            }"
            :operationCallback="sdf"
            :isPage="true"
            :pageAttributes="{
              layout: 'prev, pager, next',
              total: 1000,
              background: true
            }"
            :customColumnCallback="callback"
          >
          </createTable>

然后会看到如下效果:

image.png

或者我们在 第一列的内容 “王小虎” 前添加一个图标:

 callback(createElement, props, name) {
      return [
        createElement(
          "i",
          {
            class: ["el-icon-user-solid"]
          },
          props.row[name]
        )
      ];
    }
  },

效果如下:

image.png

至此为止配合element table 参数 基本上所有表格都能简单的实现任意效果

本文作者:admin

本文链接:https://www.javalc.com/post/26.html

版权声明:本篇文章于2020-10-15,由admin发表,转载请注明出处:分享你我。如有疑问,请联系我们

vue 使用render 动态创建element ui table

发表评论

取消
扫码支持