【Element plus】——动态表头,问题记录

记录遇到的一个奇怪问题。
在用el-table的时候,有时候表头是不固定的,还可能存在多级表头的情况,所以写了一个判断,有children的时候就迭代显示el-table-column,结果在没有子级的时候可以正常显示,在有子级的时候子级表头就显示不出来,但是加了下面这个,或者在这个地方随便放点东西(比如放几个字,如:“askdjh”)就能正常显示了,好奇怪。。。

<div>不加这个子表头显示不出来。。。</div>
<template>
  <el-table-column
    v-for="field in fields"
    :key="field"
    :prop="field[fieldProp.prop]"
    :label="field[fieldProp.label]"
    :min-width="field.minWidth ? field.minWidth : 200"
    show-overflow-tooltip
    align="center"
  >
    <!-- 显示字典 -->
    <template #default="scope" v-if="field.options && field.optionKey">
      <dict-tag :options="field.options" :value="scope.row[field.optionKey]" />
    </template>
    <template v-if="field.children && Array.isArray(field.children)">
      <div>不加这个子表头显示不出来。。。</div> 
       <!-- askdjh-->
      <custom-table-column :fields="field.children" :fieldProp="fieldProp"></custom-table-column>
    </template>
  </el-table-column>
</template>
<script lang="ts" setup name="CustomTableColumn">
import { IField, IFieldProp } from '../../ts/mixin'

const props = defineProps({
  fields: {
    //字段
    type: Array as PropType<IField[]>,
  },
  fieldProp: {
    //字段显示和使用的值
    type: Object as PropType<IFieldProp>,
    default: () => {
      return {
        prop: 'name',
        label: 'nickname',
      }
    },
  },
})
</script>


// mixin.ts文件
// 字段
export interface IField {
  name?: string //名称
  nickname?: string //中文label
  prop?: string //名称
  label?: string //中文label
  htmlType?: string
  minWidth?: number //该列的宽度
  options?: any //该列的字典类型或可选值
  optionKey?: string // 字典对应的键值
  children?: IField[]
}
// 字段使用的key值
export interface IFieldProp {
  prop: string // 用什么值
  label: string // 值的名称
}

补充————————————————————————(假装分割线)————————————————————————

重新完善了一下:
之前写的还不够自动,因为遇到需要把那列显示成按钮或者其他元素的,就需要添加一个列,而不能根据字段信息显示出来,所以重新优化了一下。而且现在不用加那段乱七八糟的也可以正常显示了。
这样就可以根据field里面的renderH函数来控制每一个字段的显示和操作了。
重点在render、h函数和component-render.vue文件里面。

<template>
  <el-table-column
    v-for="field in fields"
    :key="field.name"
    :prop="field[fieldProp.prop]"
    :label="field[fieldProp.label]"
    :min-width="field.minWidth ? field.minWidth : 200"
    show-overflow-tooltip
    :align="field.align || 'center'"
  >
    <template #default="scope" v-else-if="field.renderH">
      <componentRender :opt="field" :data="scope.row" />
    </template>
    <template v-if="field.children && Array.isArray(field.children)">
      <custom-table-column :fields="field.children" :fieldProp="fieldProp"></custom-table-column>
    </template>
  </el-table-column>
</template>
<script lang="ts" setup name="CustomTableColumn">
import { IField, IFieldProp } from '../../ts/mixin'
import componentRender from './component-render.vue'
const props = defineProps({
  fields: {
    //字段
    type: Array as PropType<IField[]>,
  },
  fieldProp: {
    //字段显示和使用的值
    type: Object as PropType<IFieldProp>,
    default: () => {
      return {
        prop: 'name',
        label: 'nickname',
      }
    },
  },
})
</script>

// component-render.vue文件
<template>
  <render />
</template>
<script setup lang="ts" name="ComponentRender">
const props = defineProps(['opt', 'data'])
const render = () => {
  let renderH = props.opt.renderH
  if (typeof renderH === 'function') {
    return renderH(props.data, props.opt)
  }
}
</script>

// mixin.ts文件
// 字段
export interface IField {
  name?: string //名称
  nickname?: string //中文label
  prop?: string //名称
  label?: string //中文label
  htmlType?: string
  minWidth?: number //该列的宽度
  options?: any //该列的字典类型或可选值
  optionKey?: string // 字典对应的键值
  children?: IField[]
  renderH?: (row: any, index: any) => globalThis.VNode<RendererNode, RendererElement, { [key: string]: any }>[] //渲染函数
}
// 字段使用的key值
export interface IFieldProp {
  prop: string // 用什么值
  label: string // 值的名称
}
//fields传入示例 
fields.value = [
    {
      name: '',
      nickname: '操作',
      renderH: (row) => {
        return [
          h(
            ElButton,
            { type: 'primary', link: true, onClick: () => handleEdit(row), icon: 'Edit' },
            { default: () => '修改' },
          ),
          h(
            ElButton,
            { type: 'danger', link: true, onClick: () => handleDelete(row), icon: 'Delete' },
            { default: () => '删除' },
          ),
        ]
      },
    },
  ]
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值