如何让 Element Plus table 组件支持 render 渲染

2,303 阅读1分钟

出现场景

在使用 Element Plus 做后台管理系统的时候,Table 表格组件往往是使用最频繁的,所以打算将表格封装一下,各个页面在使用的时候,只需要关心表格列 columns 和数据 data 即可。

封装时要考虑的问题:

  • table组件自带的属性可以直接使用
  • 在列中展示按钮、标签等信息时,使用 render 函数渲染页面元素

git地址

完整代码git地址:

掘金有一位大佬已有封装好的更完善的表格组件 ProTable戳这里查看

封装组件

创建一个组件,接收列信息 columns 和数据 data ,循环读取其中的列头信息和取值信息,如果读取到属性有 render ,则显示其返回的 VNode 内容。

<!-- components/SimpleTable.vue -->
<template>
  <el-table
    style="width: 100%"
    v-bind="$attrs"
    :data="data"
  >
    <template v-for="column in props.columns" :key="column">
      <RenderTableColumn v-bind="column" />
    </template>
  </el-table>
</template>

<script lang="tsx" setup name="SimpleTable">

const props = defineProps({
  data: Array<any>,
  columns: Array<any>
})

const RenderTableColumn = (column: any) => {
  return (
    <el-table-column>
      {{
        default: (scope: any) => {
          if (column.render) return column.render(scope)
          return scope.row[column.prop]
        },
        header: () => {
          if (column.headerRender) return column.headerRender(column)
          return column.label
        }
      }}
    </el-table-column>
  )
}

</script>

上面代码中, render 函数使用了 jsx/tsx 语法,因此需要先安装一下依赖,执行:

  • npm i @vitejs/plugin-vue-jsx -D

我这里使用的是 vite ,所以在 vite.config.ts 文件中加上:

//...
import vueJsx from '@vitejs/plugin-vue-jsx'

export default defineConfig({
  plugins: [
    vue(),
    vueJsx(),
    // ...
  ],
})

在其他页面使用

<!-- App.vue -->
<template>
  <SimpleTable :columns="columns" :data="tableData" />
</template>

<script setup lang="tsx">
import SimpleTable from './components/SimpleTable.vue'

const columns = [
  {
    label: 'Date',
    prop: 'date',
    render: (scope: any) => {
      return (
        <div style="display: flex; align-items: center">
          <el-icon><timer /></el-icon>
          <span style="margin-left: 10px">{ scope.row.date }</span>
        </div>
      )
    }
  },
  {
    label: 'Name',
    prop: 'name',
    render: (scope: any) => {
      return (
        <el-tag>{ scope.row.name }</el-tag>
      )
    }
  },
  {
    label: 'Add.',
    prop: 'address'
  },
  {
    label: 'Operations',
    prop: '',
    render: () => {
      return (
        <div>
          <el-button size="small">Edit</el-button>
          <el-button size="small" type="danger">Delete</el-button>
        </div>
      )
    }
  },
]

const tableData = [
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  }
]
</script>

在渲染列信息时,上述示例中使用 el-icon 时会发现其无法渲染,我们需要将所有的 icon 统一在 main.ts 中引入,注册成独立的组件,这样就可以在正常渲染了。

// main.ts
import { createApp } from 'vue'
import * as Icons from "@element-plus/icons-vue"
import App from './App.vue'

const app = createApp(App)

Object.keys(Icons).forEach(key => {
  app.component(key, Icons[key as keyof typeof Icons])
})
app.mount('#app')