当前位置: 首页 > news >正文

vue3+elementuiplus的table表格动态高度

table表格流体高度

1、前提

了解自定义指令、hooks

2、核心思路

通过自定义指令(new ResizeObserver)监听表格变化,然后通过hooks去更新表格高度。

3、核心代码

src/directives/resize.ts

// import { debounce } from '@/utils';

import { type Directive } from "vue";

const resizeDirective: Directive = {
  mounted(el, binding) {
    // update 要高效,否则会导致 ResizeObserver loop completed with undelivered notifications.
    // 这里通过 setTimeout 延迟实际更新到下个 tick
    let update = (entry: ResizeObserverEntry) => {
      setTimeout(() => {
        binding.value(entry);
      }, 0);
    };
    if (binding.arg) {
      try {
        let delay = Number.parseInt(binding.arg);
        console.log(delay);
        // update = debounce(binding.value, delay);
      } catch (error) {
        console.log(error);
      }
    }
    // 创建 ResizeObserver 实例
    const resizeObserver = (el.__resizeObserver__ = new ResizeObserver((entries) => {
      // 当目标元素的大小发生变化时,执行回调函数
      update(entries[0]);
    }));
    // 开始监听目标元素的大小变化
    resizeObserver.observe(el);
  },
  unmounted(el) {
    el.__resizeObserver__.disconnect();
  },
};

export default resizeDirective;

src/hooks/useTableConfig.ts

import { type TableInstance } from "element-plus";

/** 获取表格的基本配置 */
export const useTableConfig = <T>(padding: number = 20) => {
  const tableLoading = ref<boolean>(false);
  const pageData = ref<T[]>([]);
  const total = ref<number>(0);
  const tableRef = ref<TableInstance | null>(null);
  const selectedTableIds = ref<string[]>([]);

  /**表格高度 */
  const tableFluidHeight = ref<number>(0);

  const tableResize = (rect: DOMRectReadOnly) => {
    tableFluidHeight.value = rect.height - padding * 2;
  };

  return {
    tableLoading,
    pageData,
    total,
    tableRef,
    selectedTableIds,
    tableFluidHeight,
    tableResize,
  };
};

这里padding:20的原因是

 src/components/BaseTableSearchContainer/index.vue

<template>
  <div class="flex flex-col h-full">
    <slot name="search" />
    <div ref="centerRef" v-resize="onResize" class="flex-1 overflow-auto">
      <div :class="centerClass" class="p-20px bg-light-50">
        <slot name="table" />
      </div>
    </div>
    <div style="background: white">
      <slot name="pagination" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { useTemplateRef } from "vue";
defineProps({ centerClass: { type: String, default: "" } });
const emit = defineEmits(["sizeChanged"]);

const centerRef = useTemplateRef<HTMLElement>("centerRef");
const onResize = (e: ResizeObserverEntry) => {
  // console.log("resize", e, centerRef.value, centerRef.value?.getBoundingClientRect().height);
  emit("sizeChanged", e.contentRect);
};
</script>

<style lang="scss" scoped></style>

使用:

<template>
  <div class="app-container">
    <BaseTableSearchContainer @size-changed="tableResize">
      <template #search>
        <TBSearchContainer :is-show-toggle="true">
          <template #left> </template>
          <template #right> </template>
        </TBSearchContainer>
      </template>
      <template #table>
        <el-table
          ref="tableRef"
          v-loading="tableLoading"
          :data="pageData"
          highlight-current-row
          row-key="Id"
          border
          :height="tableFluidHeight"
          style="text-align: center; flex: 1"
          @select="handleTableSelect"
          @select-all="handleTableSelect"
        >
        </el-table>
      </template>
      <template #pagination>
        <Pagination
          v-if="total > 0"
          v-model:total="total"
          v-model:page="queryParams.pageIndex"
          v-model:limit="queryParams.pageSize"
          @pagination="handleGetTableList"
        />
      </template>
    </BaseTableSearchContainer>
  </div>
</template>

<script setup lang="ts">
const {
  tableLoading,
  pageData,
  total,
  tableRef,
  tableFluidHeight,
  tableResize,
} = useTableConfig<MoItemPackItem>();
</script>

<style scoped lang="scss"></style>

相关文章:

  • 1-003:MySQL 的索引类型有哪些?
  • 数据结构和算法--仅仅用于理解里面的术语,入门级别
  • github生成badges的方法
  • 大模型Transformer的MOE架构介绍及方案整理
  • 记录--洛谷 P1451 求细胞数量
  • MySQL数据库的简单练习
  • 详解分辨率、像素值与图像大小:数字图像的三大支柱
  • ospf虚拟链路配置
  • 学习资料电子版 免费下载的网盘网站(非常全!)
  • Linux Bash 单命令行解释 | 文件操作 / 字符串操作 / 重定向
  • Json工具(二)- GSON
  • 基于PyTorch的深度学习5—神经网络工具箱
  • STM32 Bootloader理解
  • LLM训练deepseek如何识别语音
  • linux 系统 之centos安装 docker
  • 【AI 大模型】RAG 检索增强生成 ⑧ ( 文本相似度排序 | Bi-Encoder 双编码器 | Cross-Encoder 交叉编码器 )
  • Docker 篇
  • IU5380C同步降压型2~4节多类型锂电池充电管理IC
  • 【形态学操作中的腐蚀和膨胀详解】
  • RuleOS:区块链开发的“破局者”,开启DApp创新的新纪元
  • 商务部回应美方加严限制中国芯片:敦促美方立即纠正错误做法
  • 马上评|这种“维权”已经不算薅羊毛,涉嫌犯罪了
  • 联合国第二届运动会闭幕,刘国梁受邀成为“联合国运动会大使”
  • 著名植物学家、园艺学家,国际植物园协会原主席贺善安逝世
  • 腾讯一季度营收增长13%,马化腾:战略性的AI投入将带来长期回报
  • 上海国际电影节纪录片单元,还世界真实色彩