Vue:用slot优化Table组件

对UI组件库table组件 columns的render优化

优化前

{
          title: "操作",
          key: "action",
          align: "center",
          fixed: "right",
          width: 300,
          render: (h, params) => {
            return h("div", [
              h(
                "Button",
                {
                  props: {
                    type: "primary",
                    size: "small"
                  },
                  style: {
                    marginRight: "5px"
                  },
                  on: {
                    click: () => {
                      this.handleDetail(params.row);
                    }
                  }
                },
                "查看"
              ),
              h(
                "Button",
                {
                  props: {
                    size: "small"
                    type: "primary",
                  },
                  style: {
                    marginRight: "5px"
                  },
                  on: {
                    click: () => {
                      this.handleChange(params.row);
                    }
                  }
                },
                "编辑"
              ),
              h(
                  "Poptip",
                  {
                    props: {
                      confirm: true,
                      transfer: true,
                      title: "您确认删除这条内容吗?",
                    },
                    on: {
                      "on-ok": () => {
                        this.handleDelete(params.row.id);
                      },
                    },
                  },
                  [
                    h(
                      "Button",
                      {
                      	props: {
                    		type: "primary",
                    		size: "small"
                  		},
                        style: {
                          color: "#5E5E5E",
                        },
                      },
                      "删除"
                    ),
                  ]
                ),
            ]);
          }
        }

在Vue2.0里,tabel组件,render这种上边写法非常见,比如操作栏,再加上Table有些显示数据要转换,render代码短则100-200行,多一点的500-600行函数,简直看得人头皮发麻。

优化后:

<template #action="{ record }">
          <Button
            type="text"
            size="small"
            style="margin-right: 5px;"
            @click="handleDetail(record.row)"
            >详情</Button
          >
          <Button
            type="text"
            size="small"
            style="margin-right: 5px;"
            @click="handleChange(record.row)"
            >修改</Button
          >
          <Poptip
            confirm
            transfer
            title="您确认删除这条内容吗?"
            @on-ok="handleDelete(record.row)"
          >
            <Button type="text" size="small" style="color:#5E5E5E">删除</Button>
          </Poptip>
      </template>

用插槽,不用写那么麻烦层层嵌套的h函数,清晰明了,不香吗?。

优化方式:
目前的UI组件库都支持slot-scope写法,只需要在你封装的tabel文件里加上 如下代码即可

		<template
          v-for="item in solts"
          :slot="item"
          slot-scope="{ row, index }"
        >
          <slot :name="item" :record="{ row, index }"> </slot>
      </template>

我简单封装的table文件如下:

<style scoped>
.zzuiTable {
  position: relative;
  min-height: 138px;
}
.table-bottom {
  margin-top: 20px;
  height: 35px;
  padding-right: 20px;
  width: 100%;
  overflow: hidden;
}
.table-btmRight {
  float: right;
}
</style>
<template>
  <div class="zzuiTable font12">
    <!--表格公用组件模板-->
    <div v-if="bool">
      <Table
        :row-class-name="rowClassName"
        :height="height"
        stripe
        size="small"
        :disabled-hover="banHover"
        :columns="columns"
        :data="dataTable.list"
        :loading="loading"
        @on-selection-change="selectChange"
        @on-sort-change="sortChange"
        @on-expand="expandTab"
        @on-select="onSelect"
      >
        <template
          v-for="item in solts"
          :slot="item"
          slot-scope="{ row, index }"
        >
          <slot :name="item" :record="{ row, index }"> </slot>
        </template>
      </Table>
      <div class="table-bottom" v-if="!pageHide">
        <div class="table-btmRight">
          <Page
            :total="dataTable.page.totalCount"
            @on-change="goPage"
            :page-size="dataTable.page.pageSize"
            :page-size-opts="[10, 30, 100, 200]"
            :current="dataTable.page.currentPage"
            @on-page-size-change="sizeChange"
            size="small"
            show-elevator
            show-sizer
            show-total
          ></Page>
        </div>
      </div>
    </div>
    <div class="center p-t-40" v-else>正在加载...</div>
  </div>
</template>
<script>
export default {
  name: "private-table",
  /* @
   * param columnsList 表格标题字段
   * param dataTable 表格数据
   * param columnsProp 通过条件判断、判断表格配置项
   * param extendColumns 通过新增表格配置项
   * */
  props: {
    columnsList: {
      type: [Array],
    },
    dataTable: {
      type: [Object],
    },
    columnsProp: {
      type: [String, Object],
    },
    extendColumns: {
      type: [String, Object],
    },
    extendWidth: {
      type: [Array, Object],
    },
    pageHide: {
      type: [String, Boolean],
      default: false,
    },
    banHover: {
      type: Boolean,
      default: false,
    },
    height: {
      type: Number,
    },
    isHadrowClassName: {
      type: Boolean,
      default: false,
    },
    loading: {
      type: Boolean,
      default: false,
    },
  },
  computed: {
    solts() {
      return Object.keys(this.$scopedSlots) || [];
    },
  },
  data() {
    return {
      bool: false,
      columns: [],
    };
  },
  watch: {
    dataTable: {
      immediate: true,
      handler: function() {
        if (this.dataTable.page && this.dataTable.list) this.formatData();
      },
    },
  },
  methods: {
    rowClassName(row, index) {
      // 提示最后一天发放金额
      if (row.step == 5 && this.isHadrowClassName) {
        let hasDay = "";
        let sendOnOff = false;
        hasDay = row.task.bonus_day_limit - row.pass_day_num;
        if (hasDay == 1 || hasDay < 1) {
          // 提示最后一天  要发放了
          sendOnOff = true;
        }
        if (sendOnOff) {
          return "colorError";
        }
      }
      return "";
    },
    /* 列表格式化 */
    formatData() {
      let arr = [];
      this.columnsList.forEach((item, index) => {
        if (item.slot) {
          arr.push(item);
        } else {
          let obj = {
            // align: item.align ? item.align : "center",
            ellipsis: item.ellipsis ? item.ellipsis : true,
            tooltip: true,
            render: (h, params) => {
              return h(
                "span",
                {
                  attrs: {
                    title: params.row[item.key],
                  },
                },
                params.row[item.key]
              );
            },
          };
          Object.assign(obj, item);
          arr.push(obj);
        }
      });
      this.columns = arr;
      this.bool = true;
    },
    /* 点击页码更换数据 */
    goPage(val) {
      this.$emit("getPageData", val);
    },
    selectChange(selection) {
      this.$emit("selectChange", selection);
    },
    expandTab(row, status) {
      this.$emit("expandTab", { row, status });
    },
    sizeChange(val) {
      this.$emit("sizeChange", val);
    },
    sortChange(val) {
      this.$emit("sortChange", val);
    },
    onSelect(val) {
      this.$emit("onSelect", val);
    },
  },
};
</script>

用法如下:


<template>
  <div class="customer">
    <Card shadow :bordered="falsse">
      <private-table
        :columnsList="tableColumns"
        :dataTable="dataTable"
        @getPageData="getPageData"
        @sizeChange="sizeChange"
        @sortChange="sortChange"
        class="margin-top-20"
      >
        <template #name="{ record }">
          {{record.row.name}}
        </template>
        <template #action="{ record }">
          <Button
            type="text"
            size="small"
            style="margin-right: 5px;color:#526ECC"
            >审核</Button
          >
          <Button
            type="text"
            size="small"
            style="margin-right: 5px;color:#526ECC"
            @click="onJumpDeatilPage(record)"
            >详情</Button
          >
        </template>
      </private-table>
    </Card>
  </div>
</template>

<script>
export default {
  name: "customer",
  data() {
    return {
     tableColumns:[
	  { title: "编号", key: "id" },
	  { title: "名称", slot: "name" },
	  { title: "状态", key: "status" },
	  { title: "创建时间", key: "time", sortable: true },
	  {
	    title: "操作",
	    slot: "action",
	    width: 200,
	    align: "center",
	  },
	],
     dataTable: [],
      page: {
        totalCount: 0,
        pageSize: 10,
        currentPage: 1,
      },

    };
  },
  mounted() {
    this.getList();
  },
  methods: {
    // 分页页数改变
    getPageData(val) {
      this.page.currentPage = val;
      this.getList();
    },
    // 每页条数改变
    sizeChange(val) {
      this.page.pageSize = val;
      this.getList();
    },
    //排序
    sortChange(e) {
      this.searchForm.sort = e.key;
      this.searchForm.order = e.order;
      if (e.order == "normal") {
        this.searchForm.order = "";
      }
      this.getList();
    },
    // 获取数据
    async getList() {
      let params = {
        pageSize: this.page.pageSize,
        pageNumber: this.page.currentPage,
        order: this.searchForm.order,
        sort: this.searchForm.sort,
      };
      this.list = [{
	    id: "79332",
	    name: "法外狂徒",
	    status: "待完善",
	    time: "2015-05-19",
	  },{
	    id: "79331",
	    name: "张三",
	    status: "待完善",
	    time: "2015-05-19",
	  }];
      this.page.totalCount = testData.length;
      this.dataTable = {
        list: this.list,
        page: this.page,
      };
    },
};
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值