Tdesign 表格实现自动撑满方法

  <div class="g-bd" ref="boxRef">
      <t-table class="m-table" row-key="index" :data="data" :columns="columns" :row-class-name="rowClassName"
        :pagination="pagination" bordered resizable lazy-load v-model:displayColumns="displayColumns"
        v-model:columnControllerVisible="columnControllerVisible">
      </t-table>
    </div>

Tdesign 表格实现自动撑满方法

1、利用CSS 撑满

.m-table {
  height: calc(100% - 64px);

  .t-table__content {
    height: 100%;

  }
}

2、使用js 设置高度

const boxRef = ref(null);
const boxHeight = computed(() => boxRef.value?.offsetHeight);
const updateContainer = () => {
  console.log('Box height:', boxHeight.value)
}

效果:

简单版参考组件,未做封装,整理 index.vue

<template>
  <div class="g-doc-wrapper" ref="docRef">
    <div class="g-doc">
      <div class="g-hd" ref="headerRef">
        <t-list>
          <t-list-item class="list-item" style="padding: 0">
            <span class="page-title">产品信息维护 </span>
            <template #action>
              <t-space>
                <t-checkbox class="item-tips" @change="onChangeFilter">隐藏筛选 {{ boxHeight }}</t-checkbox>
                <FilterDrawer></FilterDrawer>
              </t-space>
            </template>
          </t-list-item>
        </t-list>
        <div class="m-form" v-if="!HideFilter">
          <t-form ref="form" :data="formData" :layout="formData.layout" scroll-to-first-error="smooth" @reset="onReset"
            @submit="onSubmit" layout="inline" :label-width="0">
            <t-form-item label="" name="name">
              <t-input v-model="formData.name">
                <template #prefixIcon>
                  <span class="m-prefix">名字:</span>
                </template>
              </t-input>
            </t-form-item>

            <t-form-item label="" name="password">
              <t-input v-model="formData.password">
                <template #prefixIcon>
                  <span class="m-prefix">密码:</span>
                </template>
              </t-input>
            </t-form-item>
            <t-form-item>
              <t-space size="small">
                <t-button theme="primary" type="submit">查询</t-button>
                <t-button theme="default" variant="base" type="reset">重置</t-button>
              </t-space>
            </t-form-item>
          </t-form>
        </div>
        <t-divider />
        <t-list>
          <t-list-item class="list-item" style="padding-top: 0;">
            <t-space size="24px">
              <t-button theme="primary">
                <template #icon><add-icon /></template>
                新建
              </t-button>
            </t-space>
            <template #action>
              <t-space>
                <t-link class="item-tips" theme="default" @click="columnControllerVisible = true">
                  <AdjustmentIcon />
                  列表项 {{ columnControllerVisible }}
                </t-link>
              </t-space>
            </template>
          </t-list-item>
        </t-list>
      </div>
      <div class="g-bd" ref="boxRef">
        <t-table :height="boxHeight" class="table-header-class m-table" row-key="index" :data="data" :columns="columns"
          :row-class-name="rowClassName" :pagination="pagination" bordered resizable lazy-load
          v-model:displayColumns="displayColumns" v-model:columnControllerVisible="columnControllerVisible">
        </t-table>
      </div>
    </div>
  </div>



</template>
<script lang="jsx">
export default {
  name: 'DashboardBase',
};
</script>
<script setup lang="jsx">
import { ref, watch, h, computed, onMounted, onUnmounted, onBeforeUnmount, reactive, nextTick } from 'vue';
import { AdjustmentIcon, AddIcon } from 'tdesign-icons-vue-next';


import { ErrorCircleFilledIcon, CheckCircleFilledIcon, CloseCircleFilledIcon } from 'tdesign-icons-vue-next';

// import { AddIcon, CloudUploadIcon, SearchIcon, CloudDownloadIcon, DiscountIcon } from 'tdesign-icons-vue-next';
import { MessagePlugin } from 'tdesign-vue-next';


import FilterDrawer from "@/components/FilterDrawer/index.vue"

const HideFilter = ref(false);

const docRef = ref(null);
const headerRef = ref(null);
const boxRef = ref(null);

const boxHeight = ref(500)

const updateViewportHeight = () => {
  let height = boxRef.value?.offsetHeight - 64
  boxHeight.value = height >= 0 ? height : 0
};



onMounted(() => {
  updateViewportHeight(); // 初始化视口高度
  window.addEventListener('resize', updateViewportHeight, false); // 监听窗口大小变化
});

onUnmounted(() => {
  window.removeEventListener('resize', updateViewportHeight); // 移除监听
});


const onChangeFilter = (value) => {

  HideFilter.value = value;


}

const columnControllerVisible = ref(false)
const columnControllerConfig = computed(() => ({
  // 列配置按钮位置
  // placement: placement.value,
  // 用于设置允许用户对哪些列进行显示或隐藏的控制,默认为全部字段
  // fields: ['channel', 'detail.email', 'createTime', 'data1', 'data2', 'data3', 'data4'],

  // 弹框组件属性透传
  dialogProps: { preventScrollThrough: true },
  // 列配置按钮组件属性透传

  buttonProps: {
    content: '显示列控制', default: <div>

      上传文件  你看看
    </div>

  }

  // 数据字段分组显示
  // groupColumns: groupColumn.value
  //   ? [
  //       {
  //         label: '指标维度',
  //         value: 'index',
  //         columns: ['applicant', 'status', 'channel'],
  //       },
  //       {
  //         label: '次要维度',
  //         value: 'secondary',
  //         columns: ['detail.email', 'createTime'],
  //       },
  //       {
  //         label: '数据维度',
  //         value: 'data',
  //         columns: ['data1', 'data2', 'data3', 'data4'],
  //       },
  //     ]
  //   : undefined,
}));


const visibleFilter = ref(false)

const clickLink = () => {
  console.log(123)
  visibleFilter.value = !visibleFilter.value
}



// 左侧固定列发生变化时
watch(
  HideFilter,
  (val) => {
    console.log("变化啊", headerRef.value?.offsetHeight)
    nextTick(() => {
      updateViewportHeight();
    })
  },
  { immediate: true },
);


const formData = reactive({
  layout: 'inline',
  name: '',
  password: '',
});

const onReset = () => {
  MessagePlugin.success('重置成功');
};

const onSubmit = ({ validateResult, firstError }) => {
  if (validateResult === true) {
    MessagePlugin.success('提交成功');
  } else {
    console.log('Validate Errors: ', firstError, validateResult);
    MessagePlugin.warning(firstError);
  }
};


const displayColumns = ref(["index", "applicant", "status", "channel", "detail", "matters", "time", "createTime"]);

const statusNameListMap = {
  0: { label: '审批通过', theme: 'success', icon: <CheckCircleFilledIcon /> },
  1: { label: '审批失败', theme: 'danger', icon: <CloseCircleFilledIcon /> },
  2: { label: '审批过期', theme: 'warning', icon: <ErrorCircleFilledIcon /> },
};

function getData(count) {
  const data = [];
  for (let i = 0; i < count; i++) {
    data.push({
      index: i + 1,
      applicant: ['贾明', '张三', '王芳'][i % 3],
      status: i % 3,
      channel: ['电子签署', '纸质签署', '纸质签署'][i % 3],
      detail: {
        email: ['w.cezkdudy@lhll.au', 'r.nmgw@peurezgn.sl', 'p.cumx@rampblpa.ru'][i % 3],
      },
      matters: ['宣传物料制作费用', 'algolia 服务报销', '相关周边制作费', '激励奖品快递费'][i % 4],
      time: [2, 3, 1, 4][i % 4],
      createTime: ['2022-01-01', '2022-02-01', '2022-03-01', '2022-04-01', '2022-05-01'][i % 4],
    });
  }



  return data;
}

const TOTAL = 38;


function getColumns(h, { fixedLeftColumn, fixedRightColumn }) {
  return [
    {
      align: 'left',
      colKey: 'applicant',
      title: '申请人',
      foot: () => <b style="font-weight: bold">表尾信息</b>,
      width: '120',
      fixed: fixedLeftColumn ? 'left' : undefined,
    },
    {
      colKey: 'status',
      title: '申请状态',
      width: '150',
      cell: (h, { row }) => {
        return (
          <t-tag shape="round" theme={statusNameListMap[row.status].theme} variant="light-outline">
            {statusNameListMap[row.status].icon}
            {statusNameListMap[row.status].label}
          </t-tag>
        );
      },
    },
    { colKey: 'channel', title: '签署方式', width: '120' },
    { colKey: 'detail.email', title: '邮箱地址', width: '180', ellipsis: true },
    { colKey: 'matters', title: '申请事项', width: '180', ellipsis: true },
    { colKey: 'createTime', title: '申请时间', width: '120' },
    {
      colKey: 'operation',
      title: '操作',
      cell: (h, { row }) => (
        <t-link hover="color" theme="primary">
          {row.status === 0 ? '查看详情' : '再次申请'}
        </t-link>
      ),
      width: 120,
      foot: '-',
      fixed: fixedRightColumn ? 'right' : undefined,
    },
  ];
}



const data = getData(TOTAL);
// 表尾有一行数据
const footData = [{ index: 'footer-row-1', type: '全部类型', description: '-' }];
const columns = ref([]);

// 重要:如果在预渲染场景下,初次渲染的表格宽度和最终呈现宽度不一样,请异步设置表头吸顶

// type 可选值:foot 和 body
function rowClassName({ type }) {
  if (type === 'foot') return 't-tdesign__custom-footer-tr';
  return 't-tdesign__custom-body-tr';
}

function onDragSortChange({ newData }) {
  columns.value = newData;
}

const pagination = ref({ defaultCurrent: 1, defaultPageSize: 5, total: TOTAL });

const fixedLeftColumn = ref(true);
const fixedRightColumn = ref(true);
// 左侧固定列发生变化时
watch(
  fixedLeftColumn,
  (val) => {
    columns.value = getColumns(h, {
      fixedLeftColumn: val,
      fixedRightColumn: fixedRightColumn.value,
    });
  },
  { immediate: true },
);

// 右侧固定列发生变化时
watch(
  fixedRightColumn,
  (val) => {
    columns.value = getColumns(h, {
      fixedLeftColumn: fixedLeftColumn.value,
      fixedRightColumn: val,
    });
  },
  { immediate: true },
);


</script>
<style scoped lang="less">
.row-container:not(:last-child) {
  margin-bottom: 16px;
}

.g-doc-wrapper {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: solid 16px transparent;
}


.g-doc {
  width: 100%;

  display: flex;
  flex-direction: column;

  box-sizing: border-box;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 100%;

  .g-hd {
    height: auto;
  }

  .g-bd {
    flex: 1;
    height: 100%;
    overflow-y: auto;

    display: flex;
    flex-direction: column;

    box-sizing: border-box;
    position: relative;

    box-sizing: border-box;

    &::-webkit-scrollbar {
      width: 8px;
      background: transparent;
    }

    &::-webkit-scrollbar-thumb {
      border-radius: 6px;
      border: 2px solid transparent;
      background-clip: content-box;
      background-color: var(--td-scrollbar-color);
    }
  }
}

.page-title {
  font-family: PingFangSC, PingFang SC;
  font-weight: 600;
  font-size: 18px;
  color: #303133;
}

.m-form {
  margin-top: 24px;
}

.list-item {
  padding-left: 0;
  padding-right: 0;

  .item-tips {
    font-family: PingFangSC, PingFang SC;
    font-weight: 400;
    font-size: 14px;
    color: #606266;
  }
}

.m-prefix {

  font-family: PingFangSC, PingFang SC;
  font-weight: 400;
  font-size: 14px;

  color: #606266;
}
</style>


<style lang="less">
.m-table {
  height: calc(100% - 64px);

  .t-table__content {
    height: 100%;
  }
}
</style>

实战示意图

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值