vue3.0+ts+element plus 使用render函数封装表格

1. 创建文件夹 tableComponent / index.vue / tableRender.vue

index.vue

<template>
  <el-table :data="data" border tableLayout="fixed">
    <template v-for="(column, index) in columns" :key="index">
      <el-table-column
        :prop="column.prop"
        :label="column.label"
        v-if="!column.render"
      >
      </el-table-column>
      <el-table-column :label="column.label" v-if="column.render">
        <template #default="scope">
          <Render
            :renderDom="
              () => {
                return column.render(scope);
              }
            "
          />
        </template>
      </el-table-column>
    </template>
    <el-table-column label="操作" width="180" fixed="right">
      <template #default="scope">
        <el-button
          v-for="(action, index) in rowActions"
          :key="index"
          :type="action.type"
          @click="action.handler(scope.row)"
        >
          {{ action.label }}
        </el-button>
      </template>
    </el-table-column>
    <template v-slot:empty>
      <el-empty :image-size="200" />
    </template>
  </el-table>
  <div class="table-pagination">
    <el-pagination
      v-model:current-page="currentPage2"
      v-model:page-size="pageSize2"
      :page-sizes="[100, 200, 300, 400]"
      :small="small"
      :disabled="disabled"
      :background="background"
      layout="sizes,total, ->, prev, pager, next, jumper"
      :total="400"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
import Render from "./render.vue";

interface Column {
  prop: string;
  label: string;
  render?: (row: any) => string;
}

interface RowAction {
  label: string;
  type: string;
  handler: (row: any) => void;
}

export default defineComponent({
  name: "CustomTable",
  components: {
    Render,
  },
  props: {
    data: {
      type: Array,
      required: true,
    },
    columns: {
      type: Array as () => Column[] | any,
      required: true,
    },
    rowActions: {
      type: Array as () => RowAction[] | any,
      required: true,
    },
  },
  emits: ["onChangePage", "onChangeLimit"],
  setup(_props, { emit }) {
    const currentPage2 = ref(4); //当前页码
    const pageSize2 = ref(10); // 每页条数
    const disabled = ref(false);
    const small = ref(false);
    const background = ref(false);
    const handleSizeChange = (val: number) => {
      emit("onChangeLimit", val);
      console.log(`${val} 每页显示多少条`);
    };
    const handleCurrentChange = (val: number) => {
      emit("onChangePage", val);
      console.log(`当前页: ${val}`);
    };
    return {
      pageSize2,
      currentPage2,
      handleSizeChange,
      handleCurrentChange,
      disabled,
      small,
      background,
    };
  },
});
</script>
<style lang="scss">
.table-pagination {
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  padding: 13px 15px;
  background-color: #fafafa;
  // justify-content: center;
}
</style>

2. render.vue

<template></template>
<script lang="ts">
import { defineComponent, h, PropType, VNode } from "vue";
interface RenderProps {
  renderDom: (hFunc: typeof h) => VNode;
}
export default defineComponent({
  name: "Render",
  props: {
    renderDom: {
      type: Function as PropType<(hFunc: typeof h) => VNode>,
      required: true,
    },
  },
  setup(props: RenderProps) {
    // return () => h("div", {}, props.renderDom(h));
    return props.renderDom;
  },
});
</script>

3. 页面中使用

<template>
  <div class="table">
    <CustomTable
      :data="tableData"
      :columns="tableColumns"
      :rowActions="tableActions"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, h, ref } from "vue";
import CustomTable from "@/components/tableComponent/index.vue";
import { ElSwitch } from "element-plus";
export default defineComponent({
  name: "MyPage",
  components: {
    CustomTable,
  },
  setup() {
//表格数据
    const tableData = ref([
      { id: 1, name: "John", age: 30, status: true },
      { id: 2, name: "Jane", age: 25, status: true },
      { id: 3, name: "Bob", age: 35, status: true },
    ]);
//表头
    const tableColumns: any = [
      { prop: "id", label: "ID" },
      { prop: "name", label: "用户名" },

          // 普通的html元素
          // return h(
          //   "span",
          //   {
          //     class: "my-component",
          //     style: { color: "red" }, //可动态
          //   },
          //   scope.row.age
          // );
          // element的
        render: (scope: any) => {
          return h(ElSwitch, {
            modelValue: scope.row.status,
            "inline-prompt": true,
            "active-text": "是",
            "inactive-text": "否",
            "active-value": 1,
            "inactive-value": 0,
            size: "large",
            "onUpdate:modelValue": (value: string | boolean | any) => {
              scope.row.status = value;
              // 这里可以处理其他逻辑
            },
           
          });
        },
      },
    ];
    //操作栏
    const tableActions = [
      {
        label: "编辑",
        type: "primary",
        handler: (row: Object) => handleEdit(row),
      },
      {
        label: "删除",
        type: "danger",
        handler: (row: Object) => handleDelete(row),
      },
    ];
    const handleEdit = (row: Object) => {
      console.log("Edit row:", row);
    };
    const handleDelete = (row: Object) => {
      console.log("Delete row:", row);
    };

    return {
      tableData,
      handleEdit,
      handleDelete,
      tableActions,
      tableColumns,
    };
  },
});
</script>

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值