在VUE3.x项目中二次封装ElementUI Plus El-Table组件

142 阅读3分钟

在VUE3.x项目中二次封装ElementUI Plus El-Table组件

(先回忆初恋放松下)

1.应用场景

相信同志们在写后台管理的项目时,表格组件是使用最多的一个组件了。尽管饿了么中的ElTable已经非常的完善了,但抵不住数量的庞大,正常的流程可能就是cv官方的代码然后再修改一下,那有没有一劳永逸的方法呢?当然,哥几个把表格二次封装一下就能很好的解决这个问题了。
下面是修沟在工作中常用的两种封装方式。

2.二次封装

2.1 low点的封装

为什么说叫low点的封装呢,因为与第二方式的比较,观众老爷们心里会有答案的。
话不多说先上代码
<script setup>
    const props = defineProps({
      tableData: {
        type: Array,
        default: () => [],
      },
      colItems: {
        type: Array,
        default: () => [],
      },
    });
</script>

<template>
<el-table
        ref="refTable"
        :data="tableData"
        style="width: 100%; height: 100%"
        @row-dblclick="
          (row, col, event) =>; {
            emit('handleRowDblclick', row, col, event);
          }
        "
      >;
        <el-table-column v-if="showCheckBox" type="selection" width="50">;</el-table-column>;
        <el-table-column v-if="showIndex" type="index" label="序号" width="80">;</el-table-column>;
        <el-table-column
          v-for="item in colItems"
          :key="item.prop"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :align="item.align"
        >;</el-table-column>;
      </el-table>;
</template>

上述的封装方式应该是大家在工作中比较常见的一种方式,使用起来也非常的简单。

2.2 别样的封装

相较于上一种的封装方式,这种方式区别还是挺大的,也是笔者在工作常用的封装方式。
先上代码
import {
  getCurrentInstance,
  h,
  toRefs,
  useAttrs,
  ref,
  defineComponent,
} from "vue";
import { ElTable, ElTableColumn } from "element-plus";
import "element-plus/dist/index.css";

export default defineComponent({
  props: {
    columns: {
      type: Array,
      default: () => [],
    },
  },

  setup(props) {
    const attrs = useAttrs();

    const { columns } = toRefs(props);

    const getTableColumn = (column) => {
      const { children, render, ...data } = column;
      const slots = {};
      if (render) {
        slots.default = render;
      }
      if (children) {
        slots.default = () =>
          children.map((childColumn) => {
            return getTableColumn(childColumn);
          });
      }
      return h(
        ElTableColumn,
        {
          ...data,
        },
        slots.default
      );
    };
    const tableColumns = () =>
      columns.value.map((column) => {
        return getTableColumn(column);
      });

    const instance = getCurrentInstance();

    instance.render = () => {
      return h(
        ElTable,
        {
          ref: "refElTable",
          ...attrs,
        },
        tableColumns
      );
    };

    const refElTable = ref();
    return {
      refElTable,
    };
  },
});
看完上述代码,可能各位观众老爷会有疑问?整个代码块中没有一个HTML,那到底是怎么渲染成一个组件的呢?在这里就不得不提一下VUE中的 [h函数](https://cn.vuejs.org/api/render-function.html#h) 了。
创建虚拟 DOM 节点 (vnode)。VUE官方文档中对h函数的解释就这么一句话,非常简单,详情的用法可以去官网上查看,在此就不做陈述了。上述代码的逻辑其实也非常简单,通过h函数渲染出一个vnode,然后再setup钩子函数中调用render方法去渲染vnode。
使用示例代码如下:
<script setup>
import { ref } from "vue";
import CustomTable from "./components/CustomTable/CustomTable.vue";
const data = ref([
  {
    name: "xxx",
    gender: "men",
  },
]);
const columns = [
  {
    prop: "name",
    label: "姓名",
  },
  {
    prop: "gender",
    label: "性别",
  },
];
const handleCustomTableSelect = () => {}

const refCustomTable = ref(null)
// 调用el-table的方法
refCustomTable.value.refElTable.clearSelection()
</script>

<template>
  <div class="main">
    <CustomTable ref="refCustomTable" :data="data" :columns="columns" @select="handleCustomTableSelect" />
  </div>
</template>
属性和方法的使用方式和ElTable组件一样,有点出入的就是调用ElTable的方法。
其中h函数其实非常强大,我们可以围绕去实现更多、更简洁的功能

3.二者的区别

初恋回忆录,放松一下观众老爷们

放松完了咱们继续,其实第一种封装已经能够满足大多数场景了,那为什么还要去深究第二种呢。主要的原因是第一种封装不太能满足功能时,第二种方式能够更多样化的去完成表格。因为当slot用的多时候,我们就要在第一种封装中疯狂的if else,一个两个还好,相信大家都不愿意写太多的if else。在第二种方式中,我们能够利用h函数的特性去手动控制表格单元格中渲染的内容。
那么这期的实用小技巧就到此结束了,希望观众老爷们在工作时放松下来,敲出诗一样的代码。