其他分享
首页 > 其他分享> > el-table二次封装

el-table二次封装

作者:互联网

<template>
  <div style="margin: 20px 20px 100px 20px">
    <el-table
      border
      class="customer-no-border-table"
      element-loading-text="数据正在加载中..."
      :row-class-name="tableRowClassName"
      :header-cell-style="{ background: '#E7F2FD', color: '#252525' }"
      style="width: 100%; border-top: 1px solid #409eff"
      v-loading="loading"
      :ref="tableName"
      :data="tableData"
      :highlight-current-row="light"
      @row-click="getrow"
      @sort-change="sortChange"
      @selection-change="handleSelectionChange"
      :row-key="rowKey"
      :reserve-selection="reserve"
      :max-height="fixedHeight > 0 ? fixedHeight : tableHeight - difference"
    >
      <!-- 复选框 -->
      <el-table-column
        type="selection"
        v-if="choice"
        width="50"
        :align="headerAlign"
        :key="Math.random()"
      >
      </el-table-column>
      <!-- 序号 -->
      <el-table-column
        label="序号"
        v-if="serialNumber"
        width="50"
        type="index"
        :align="headerAlign"
        :key="Math.random()"
      >
      </el-table-column>
      <!-- 动态表头 -->
      <!-- {
                prop:'title',// 列表渲染的字段key
                label:'菜单名称',// 字段中文名称
                align:''// 列表内容文字的位置
                sort:true, // 是否排序
                form:'string', (可选:string/img/Button/filter/select)
                key:{label: "label",value: "value"} // 这个配置是下拉框的form = select
                filter(row){},// 对数据进行过滤 并返回内容 和vue 过滤器一样的功能
                configure:{ // 配置按钮的参数对象
                    type:''// 参考el-button 官网参数
                    size:''// 参考el-button 官网参数
                },
                callback(row){} //点击按钮的回调函数
            } -->
      <div v-for="(item, index) in tableLabel" :key="index">
        <!-- 普通数据展示/或者字符串文本展示 -->
        <el-table-column
          v-if="!item.form || item.form === 'string'"
          :prop="item.prop"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'center'"
          :key="index"
          show-overflow-tooltip
        >
        </el-table-column>
        <!-- 数据过滤:根据filter函数自定义规则进行数据返回 -->
        <el-table-column
          v-else-if="item.form === 'filter'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'center'"
          :key="index"
          show-overflow-tooltip
        >
          <template slot-scope="scope">
            {{ item.filter(scope.row) }}
          </template>
        </el-table-column>
        <!-- 图片展示 -->
        <el-table-column
          v-else-if="item.form === 'img'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'center'"
          :key="index"
        >
          <template slot-scope="scope">
            <!-- 如果是字符串就是一个图片 -->
            <div v-if="typeof scope.row[item.prop] === 'string'">
              <el-image
                style="width: 22px; height: 22px"
                :src="scope.row[item.prop] ? scope.row[item.prop] : defaultImg"
                :preview-src-list="[
                  scope.row[item.prop] ? scope.row[item.prop] : defaultImg,
                ]"
              >
              </el-image>
            </div>
            <!-- 不是字符串就统一数组来处理 -->
            <div
              v-else-if="
                scope.row[item.prop] !== null && scope.row[item.prop].length > 0
              "
            >
              <span
                v-for="(item1, index1) in scope.row[item.prop]"
                :key="index1"
              >
                <el-image
                  style="width: 22px; height: 22px; margin-right: 20px"
                  :src="scope.row[item.prop][index1]"
                  :preview-src-list="scope.row[item.prop]"
                  :z-index="2100"
                >
                </el-image>
              </span>
            </div>
          </template>
        </el-table-column>
        <!-- 按钮展示 -->
        <el-table-column
          v-else-if="item.form === 'Button'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'center'"
          :key="index"
        >
          <template slot-scope="scope">
            <el-button
              @click="item.callback && item.callback(scope.row)"
              :type="
                item.configure && item.configure.type ? item.configure.type : ''
              "
              :size="
                item.configure && item.configure.size ? item.configure.size : ''
              "
            >
              {{ item.configure.text || "缺少按钮文字" }}</el-button
            >
          </template>
        </el-table-column>
        <!-- 多个复选框 -->
        <el-table-column
          v-else-if="item.form === 'checkbox'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'center'"
          :key="index"
        >
          <template slot-scope="scope">
            <span
              style="margin-left: 5px"
              v-for="(v, i) in scope.row.authority"
              :key="i"
            >
              <el-checkbox
                :label="v.name"
                name="type"
                v-model="v.open"
              ></el-checkbox>
            </span>
            <span v-if="scope.row.authority && scope.row.authority.length < 1"
              >暂无</span
            >
          </template>
        </el-table-column>
        <!-- 单选框 -->
        <!-- 表头配置tableLabel -->
        <!-- {
                        prop: 'timeType',最终下拉框每次选中的值都绑定到 这个定义的字段上
                        label: '时间单位',
                        align: 'center',
                        form: "radio",
                        key: {
                            label: "label",
                            value: "value"
                        },
                        width: 250,
                    }, -->
        <!-- 列表循环数据 每一项必须要有 radioList属性为数组 -->
        <el-table-column
          v-else-if="item.form === 'radio'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'center'"
          :key="index"
        >
          <template slot-scope="scope">
            <div v-if="scope.row.radioList && scope.row.radioList.length">
              <el-radio-group v-model="scope.row[item.prop]">
                <el-radio
                  v-for="items in scope.row.radioList"
                  :key="items[item.key.value]"
                  :label="items[item.key.value]"
                  >{{ items[item.key.label] }}</el-radio
                >
              </el-radio-group>
            </div>
            <div v-else>
              <span style="color: #e6a23c">缺少radioList属性数组!</span>
            </div>
          </template>
        </el-table-column>
        <!-- 下拉框 -->
        <!-- 表头配置tableLabel -->
        <!-- {
                    prop:'xxx' 最终下拉框每次选中的值都绑定到 这个定义的字段上
                    form:'select',
                    key:{label: "label",value: "value"}
                } -->
        <!-- 列表循环数据 每一项必须要有 options属性为数组 -->
        <el-table-column
          v-else-if="item.form === 'select'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'left'"
          :key="index"
        >
          <template slot-scope="scope">
            <el-select
              v-model="scope.row[item.prop]"
              placeholder="请选择"
              size="mini"
            >
              <el-option
                v-for="items in scope.row.options"
                :key="items[item.key.value]"
                :label="items[item.key.label]"
                :value="items[item.key.value]"
              >
              </el-option>
            </el-select>
          </template>
        </el-table-column>
        <!-- 输入框 -->
        <el-table-column
          v-else-if="item.form === 'input'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'left'"
          :key="index"
        >
          <template slot-scope="scope">
            <el-input
              placeholder="请输入内容"
              v-model="scope.row[item.prop]"
              size="mini"
            >
            </el-input>
          </template>
        </el-table-column>
        <!-- 自定义 -->
        <el-table-column
          v-else-if="item.form === 'my'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'center'"
          :key="index"
          show-overflow-tooltip
        >
          <template slot-scope="scope">
            <span
              style="text-decoration: underline; color: blue"
              @click="item.callback(Object.assign({}, scope.row))"
              >{{ item.filter(scope.row) }}</span
            >
          </template>
        </el-table-column>
        <!-- 固定列 -->
        <el-table-column
          v-else-if="item.form === 'fixed'"
          :width="item.width"
          :label="item.label"
          :sortable="item.sort"
          :align="item.align ? item.align : 'center'"
          :key="index"
        >
        </el-table-column>
      </div>

      <el-table-column
        label="操作"
        :width="operation.width"
        v-if="JSON.stringify(operation) !== '{}'"
      >
        <template slot-scope="scope">
          <!-- 操作按钮 -->
          <!-- {
                        label:'删除',
                        type:'danger',// 按钮类型  参考el-button 官网参数
                        size:"mini", // 按钮大小  参考el-button 官网参数
            plain:true, // 是否朴素按钮
                        callback(row){}, // 点击按钮回调函数
                        disabled(row){ return true/false} //是否禁用 可以条件判断 让函数返回布尔值
                        authority:true// 如果涉及到权限按钮控制的 就添加这个属性(false普通按钮/true权限按钮)
                        authorityEvent(row){return true/false}
                    } -->
          <!-- 动态操作按钮 -->
          <div class="flex center">
            <div
              class="flex center"
              v-for="(item, index) in operation.Button"
              :key="index"
            >
              <el-button
                style="margin: 0 5px"
                v-if="!item.authority"
                @click="item.callback(Object.assign({}, scope.row))"
                :type="item.type ? item.type : ''"
                :size="item.size ? item.size : ''"
                :disabled="item.disabled && item.disabled(scope.row)"
                :plain="plain"
                >{{ item.label }}</el-button
              >
              <el-button
                style="margin: 0 5px"
                v-else-if="
                  item.authority &&
                  item.authorityEvent &&
                  item.authorityEvent(item.label)
                "
                @click="item.callback(Object.assign({}, scope.row))"
                :type="item.type ? item.type : ''"
                :size="item.size ? item.size : ''"
                :disabled="item.disabled && item.disabled(scope.row)"
                :plain="plain"
                >{{ item.label }}</el-button
              >
            </div>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div
      style="padding: 10px"
      v-if="paging"
      :style="{ 'text-align': pagingPosition }"
    >
      <el-pagination
        @size-change="handleNumberChange"
        @current-change="handleCurrentPage"
        :current-page="searchData.page"
        :page-sizes="[10, 15, 20, 30, 40, 50]"
        :page-size="searchData.limit"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      >
      </el-pagination>
    </div>
  </div>
</template>

<!-- /**
 * 组件说明
 * 属性:
 * 参数                     说明                           类型                    默认值
 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 * tableData              列表 的数据源                   Array                      []
 * treeProps              支持树类型的数据的列表显示       Object                     {children: 'children'}
 * rowKey                 树类型的数据 列表必须要指定        String                     '_id'
 * serialNumber           是否需要序号                     Boolean                    true
 * headerAlign               表头对齐方式/复选框/序号              String                    'left'/'center'/'right'
 * tableLabel               动态表头渲染数组                Array                     []
 * choice                   是否开启多选复选框                Boolean                 false
 * operation               操作列表按钮                    Object                     {}
 * total                   分页总页数                     number                     0
 * paging                   是否开启分页                     Boolean                 false
 * pagingPosition           分页底部的位置                     String                     'left'/'center'/'right'
 * fixedHeight               固定table列表高度                 number                      0
 * pagingPage               分页参数                         Object                     {pageSize: 20,page: 1}
 * headButton             列表头部按钮是否显示              Boolean                   false

 * 回调事件:
 * select  获取复选框选中对象 返回数组
 * sortChange     获取当前点击表头指定排序结果
 * handleCurrentPage     每次切换页数触发并且回调页数
 * handleNumberChange     每次切换展示的条数触发并且回调
 */ -->
<script>
const defaultImg = require("../assets/nodata.png");
export default {
  props: {
    // ref的名字
    tableName: {
      type: String,
      default: "",
    },
    // 是否记忆分页选中行
    reserve: {
      type: Boolean,
      default: false,
    },
    // 是否高亮当前行
    ligth: {
      type: Boolean,
      default: false,
    },
    // 是否朴素按钮
    plain: {
      type: Boolean,
      default: true,
    },
    // 数据
    tableData: {
      type: Array,
      default: () => [],
    },
    // 支持树类型的数据的显示
    treeProps: {
      type: Object,
      default: () => ({
        children: "children",
      }),
    },
    //树类型的数据 列表必须要指定row-key id
    rowKey: {
      type: String,
      default: "_id",
    },
    // 是否需要序号
    serialNumber: {
      type: Boolean,
      default: true,
    },
    // 表头对齐方式
    headerAlign: {
      type: String,
      default: "center",
    },
    // 表头
    tableLabel: {
      type: Array,
      default: () => [],
    },
    // 复选框
    choice: {
      type: Boolean,
      default: false,
    },
    // 操作按钮参数
    operation: {
      type: Object,
      default: () => ({}),
    },
    // 总条数
    total: {
      type: Number,
      default: 0,
    },
    //分页
    paging: {
      type: Boolean,
      default: false,
    },
    // 分页组件位置
    pagingPosition: {
      type: String,
      default: "left",
    },
    // 固定高度
    fixedHeight: {
      type: Number,
      default: 0,
    },
    // 分页组件参数
    pagingPage: {
      type: Object,
      default: () => ({
        limit: 10,
        page: 1,
      }),
    },
    // 设置偏移高度(到达每个页面不同内容高度,都可以让列表高度填充满整个可视区)
    difference: {
      type: Number,
      default: 0,
    },
  },
  data() {
    return {
      defaultImg: defaultImg,
      tableHeight: document.documentElement.clientHeight - (70 + 80), // 表格自适应高度 默认撑满
      // 分页固定参数
      searchData: {
        limit: this.pagingPage.limit,
        page: this.pagingPage.page,
      },
    };
  },
  methods: {
    tableRowClassName({ rowIndex }) {
      if (rowIndex % 2 === 1) {
        return "success-row";
      }
      return "";
    },

    // 重置分页参数
    pagingReset(limit, page) {
      if (!limit && !page) {
        this.searchData.limit = 10;
        this.searchData.page = 1;
      } else if (limit) {
        this.searchData.limit = limit;
      } else {
        this.searchData.page = page;
      }
    },
    // 切换页数
    handleCurrentPage(val) {
      this.searchData.page = val;
      this.$emit("handleCurrentPage", val);
    },
    // 每页N展示条
    handleNumberChange(val) {
      this.searchData.limit = val;
      this.$emit("handleNumberChange", val);
    },
    //选中当前行
    getrow(row) {
      this.$emit("getrow", row);
    },
    // 复选框勾选
    handleSelectionChange(array) {
      console.log(array, "array");
      this.$emit("handleSelectionChange", array);
    },
    // 排序
    sortChange(column, prop, order) {
      console.log(column, "column");
      console.log(prop, "prop");
      console.log(order, "order");
      this.$emit("sortChange", column);
    }
  },
};
</script>
<style scoped lang='less'>
/* 默认el-table 行高过于高,这里设置减少padding之间的间距 */
/deep/ th {
  padding: 9px 0;
}

/deep/ .el-table td {
  padding: 9px 0;
}
</style>

  

<template>
  <div>
    <table-List
      :tableData="tableData"
      :tableLabel="tableLabel"
      :choice="choice"
      :light="light"
      :reserve="reserve"
      :paging="paging"
      :operation="operation"
      :total="total"
      pagingPosition="center"
      headerAlign="center"
      @sortChange="sortChange"
      @getrow="getrow"
      @handleSelectionChange="handleSelectionChange"
      @handleNumberChange="handleNumberChange"
      @handleCurrentPage="handleCurrentPage"
    >
    </table-List>
  </div>
</template>

<script>
import tableList from "./table.vue";
export default {
  components: {
    tableList,
  },
  data() {
    return {
      light: true, //高亮当前行
      paging: true, //是否分页
      pagingPage: {
        limit: 10,
        page: 1,
      },
      tableData: [
        { nickName: "111", friendCount: 123 },
        { nickName: "222", friendCount: 456 },
      ], //数据源
      tableLabel: [
        {
          prop: "nickName",
          label: "用户昵称",
          align: "center",
          form: "filter",
          filter(row) {
            if ((row.nickName = "111")) {
              return `丫丫`;
            } else {
              return "哈哈";
            }
          },
        },
        {
          prop: "friendCount",
          label: "好友数量",
          align: "center",
          form: "my",
          filter(row) {
            if (row.friendCount == "123") {
              return `百度`;
            } else {
              return "billbill";
            }
          },
          callback: (row) => {
            if (row.friendCount == "123") {
              window.open("https://www.baidu.com/?tn=02003390_19_hao_pg");
            } else {
              window.open("https://blog.csdn.net/jlsdzhj/article/details/80647682");
            }
          },
        },
      ],
      operation: {
        width: "220",
        Button: [
          {
            label: "查看",
            size: "mini",
            authority: false,
            callback(k) {
              console.log(k);
            },
          },
        ],
      },
      total: 0,
    };
  },
  methods: {
    // 分页
    handleNumberChange(val) {
      console.log(val, "当前页码");
    },
    // 每一页展示多少条切换
    handleCurrentPage(val) {
      console.log(val, "当前展示条数");
    },
    // 排序
    sortChange(column) {
      console.log(column, "column");
    },
    //多选
    handleSelectionChange(array) {
      console.log(array, "array");
      this.selectList = array;
    },
    // 单选
    getrow(row) {
      console.log(row, "选中行");
      this.trData = row;
    },
  },
};
</script>

<style lang="scss" scoped>
</style>





components:{tableList,
},
data(){
    return{
        tableData: [
        {nickName:"111",friendCount:123,},{nickName:"222",friendCount:456},{}],//数据源
        tableLabel:[
            {
            prop: 'nickName',
            label: '用户昵称',
            align: 'center',
            form:'filter',
            filter(row){
              if(row.nickName='111'){
                return '丫丫'
              }else{
                return '哈哈'
              }
            }
          },
           {
            prop: 'friendCount',
            label: '好友数量',
            align: 'center',
          },
        ],
        operation:{
            width: '220',
            Button:[
             {
                  label: '查看',
                  size: "mini",
                  authority: false,
                  callback(k) {
                        console.log(k)
                  }
                }
            ]
        },
        total:10,
        
    }
} ,
methods:{
    handleNumberChange(val){},// 每一页展示多少条切换
    handleCurrentPage(val){},//切换分页
    sortChange(column){},// 排序
    select(valArr){},//列表复选框
}             

  

标签:el,封装,val,default,console,return,table,type,row
来源: https://www.cnblogs.com/hxy--Tina/p/16662976.html