在vue3中使用element-plus的表格组件,使用对象动态自定义配置列数据(render)

587 阅读1分钟

由于elementUI没有直接提供列数据render渲染,我们只能使用template插槽,这看似能够自定义,实际上还是无法满足所有场景

1、一个简单的表格场景

<el-table :data="data" style="width: 100%" size="large">
  <template v-for="item in column" :key="item.prop">
    <el-table-column
      v-if="item.render"
      :label="item.label"
      :width="item.width"
    >
      <template #default="scoped">
        <custom-column
          :scoped="scoped"
          :item-column="item"
          :onCommand="onCommand"
        />
      </template>
    </el-table-column>
    <el-table-column
      v-else
      :width="item.width"
      :prop="item.prop"
      :label="item.label"
    />
  </template>
</el-table>

<script setup lang="ts">
import { column, CustomColumn } from "./column";
import { ref } from "vue";
const data = ref([
  {
    name: "张三",
    phone: "12345678901",
  },
]);

// 操作按钮的下拉选择
const onCommand = (command: string, scoped: any) => {
  console.log(command, scoped);
};
</script>

2、引入列配置

// 这里我用的tsx文件,column.tsx
import { column, CustomColumn } from "./column";

3、column 文件内容

import { defineComponent } from "vue";
import {
  ElDropdown,
  ElIcon,
  ElDropdownMenu,
  ElDropdownItem,
} from "element-plus";
import styles from "./column.module.less";

/**
* column render 转换成组件
* 这里是重点、需用组件把自定义的render函数包裹返回,不然会报错
* 然后再第二步引入配置,去使用这个导出的组件 CustomColumn
*/ 
export const CustomColumn = defineComponent({
  props: {
    scoped: {
      type: Object,
    },
    itemColumn: {
      type: Object,
    },
  },
  setup(props: any) {
    const { itemColumn } = props;
    return () => <itemColumn.render {...props} />;
  },
});

export interface Column {
  prop: string;
  label: string;
  width?: string;
  render?: (row: any) => any;
}
export const column: Column[] = [
  {
    prop: "name",
    label: "姓名",
  },
  {
    prop: "phone",
    label: "手机号",
  },
  {
    prop: "date",
    label: "加入时间",
  },
  {
    prop: "role",
    label: "角色",
  },
  {
    prop: "inviter",
    label: "邀请人",
  },
  {
    prop: "status",
    label: "状态",
  },
  {
    prop: "opreation",
    label: "操作",
    render: (props) => {
      const { onCommand, scoped } = props;
      const handleCommand = (type: string) => {
        onCommand?.(type, scoped);
      };
      return (
        <div class={styles.opreation}>
          <ElDropdown class={styles["dropdown"]} onCommand={handleCommand}>
            {{
              default: () => (
                <span class={styles["el-dropdown-link"]}>
                  <span style={{ marginRight: "5px" }}>修改</span>
                  <ElIcon>
                    <arrow-down />
                  </ElIcon>
                </span>
              ),
              dropdown: () => (
                <ElDropdownMenu>
                  <ElDropdownItem command="updateName">
                    修改备注名
                  </ElDropdownItem>
                  <ElDropdownItem command="updateRole">修改角色</ElDropdownItem>
                </ElDropdownMenu>
              ),
            }}
          </ElDropdown>
          <ElButton link type="danger">
            移除
          </ElButton>
        </div>
      );
    },
  },
];