vue3监听容器大小修改el-table表格最大高度和默认条数

需求:

  1. 用户进入页面时,要设置一下内容区域中表格默认条数和表格最大高度;
  2. 当容器高度变化时,表格的最大高度也需要修改(比如从大屏拖到笔记本)

环境:vue3+ts+elementplus

因为页面表格都需要,所以封装成一个方法,以下是utils/watchContainerHeight.ts代码:

数据必须使用Ref定义,不然不会是响应式的!!!
注意:在页面调用时,优先于其他生命周期!!!
说明:搜索项会做响应式,所以这个表格高度是会受到影响的,两个场景解决亲测有效~

场景一

场景描述

内容区域界面布局采用的是两个card,参照下图(其中第二个crad的按钮区域可有可有,两种情况都会考虑)
在这里插入图片描述

解决方案

主要函数代码如下:

import { onMounted, onBeforeUnmount, Ref } from 'vue';
import type { CardInstance } from 'element-plus';

// 监听列表card高度,从而计算表格最大高度并设置默认条数
export function useTableDynamicHeight(
  listCardRef: Ref<CardInstance | null>,
  maxHeightRef: Ref<number>,
  pageSizeRef: Ref<number>
) {
  const watchHeight = () => {
    if (listCardRef.value) {
      const tableHeight = listCardRef.value?.$el.offsetHeight;
      // 判断界面是否有主操作按钮 -- 界面必须使用同一套样式
      if (listCardRef.value?.$el.querySelector('.operate-btns')) { // 类名看自己项目定义
        // card上下内边距48,按钮区域:32,分页:32
        // 至于46和23,猜测是margin或padding,不减这个会压着分页组件,感兴趣的话可以看看是什么
        maxHeightRef.value = tableHeight - (48 + 64 + 46);
      } else {
        maxHeightRef.value = tableHeight - (48 + 32 + 23);
      }
    }
  };

  onMounted(() => {
    window.addEventListener('resize', watchHeight);
    if (listCardRef.value) {
      watchHeight()
      // 看项目需求调整
      if (maxHeightRef.value < 600) {
        pageSizeRef.value = 10;
      } else {
        pageSizeRef.value = 20;
      }
    }
  });

  onBeforeUnmount(() => {
    window.removeEventListener('resize', watchHeight);
  });
}

页面调用:

<template>
  <div class="list-container">
    <el-card class="search-card">
      <!-- 搜索项和按钮 -->
    </el-card>
    <el-card class="list-card" ref="listCardRef">
      <!-- 也可以没有操作按钮 -->
      <div class="operate-btns">
        <el-button type="primary">新增</el-button>
      </div>
      <div class="table-box">
        <el-table border :data="tableData" style="width: 100%" row-key="id" header-align='center'
          :default-expand-all="false" empty-text="暂无数据" :max-height="maxHeight">
			<!-- 列 -->
          </el-table-column>
        </el-table>
        <div class="pagination"></div>
      </div>
    </el-card>
  </div>
  <router-view />
</template>

<script setup lang="ts">
import { reactive, ref, onMounted } from "vue";
// 1. 引入方法和card类型
import type { CardInstance } from "element-plus"
import { useTableDynamicHeight } from '@/utils/watchContainerHeight'

// 2. 定义所需变量
const tableData = ref([])
const maxHeight = ref() // 表格最大高度
const currentPage = ref(1); // 当前页
const pageSize = ref(10); // 每页显示的条数
const listCardRef = ref<CardInstance | null>(null)
// 3. 调用方法
useTableDynamicHeight(listCardRef, maxHeight, pageSize)  // 在onMounted方法上面!!!

onMounted(() => {});
</script>
<style scoped lang="less"></style>

场景二

场景描述

适用于搜索和表格在同一个crad里面,中间使用分割线区分

import { onMounted, onBeforeUnmount, Ref } from 'vue';

export function useContainerHeight(
  containerRef: Ref<HTMLElement | null>,
  searchFormRef: Ref<HTMLElement | null>,
  maxHeightRef: Ref<number>,
  pageSizeRef: Ref<number>
) {
  const watchHeight = () => {
    if (containerRef.value && searchFormRef.value) {
      const height = containerRef.value.offsetHeight;
      const searchHeight = searchFormRef.value.offsetHeight;
      if (containerRef.value?.querySelector('.operate-btns')) {
        maxHeightRef.value = height - 48 - searchHeight - 48 - 64 - 46;
      } else {
        maxHeightRef.value = height - 48 - searchHeight - 48 - 64;
      }
    }
  };

  onMounted(() => {
    window.addEventListener('resize', watchHeight);
    if (containerRef.value && searchFormRef.value) {
      watchHeight()
      // 可以根据项目需求自己设置,如果需要高度变化,默认条数也变,可以把下面这段逻辑加到watchHeight中
      if (maxHeightRef.value < 600) {
        pageSizeRef.value = 10;
      } else {
        pageSizeRef.value = 20;
      }
    }
  });

  onBeforeUnmount(() => {
    window.removeEventListener('resize', watchHeight);
  });
}

页面调用:

<template>
  <div class="container" ref="container">
      <div ref='searchRef'>搜索区</div>
  	  <el-divider />
	  /** 页面其他逻辑,只写到了需要的参数,其他参数根据官网和需求自己加哦~ **/
	  <el-table :max-height="maxHeight">
	  </el-table>
	  <el-pagination v-model:page-size="pageSize" :background="true" />
   </div>
</template>
<script setup lang="ts">
	import { ref, onMounted } from "vue";
	import { useContainerHeight } from '@/utils/watchContainerHeight'
	const currentPage = ref(1); // 当前页
	const pageSize = ref(10); // 每页显示的条数
	const container = ref<HTMLElement | null>(null)
	const searchRef= ref<HTMLElement | null>(null)
	useContainerHeight(container, searchRef, maxHeight, pageSize) // 优先于其他生命周期
	onMounted(()=>{})
</script>
### 如何在 Vue 3 中自定义 Element Plus `el-table` 的滚动条样式 在 Vue 3 Element Plus 开发中,如果需要修改 `el-table` 默认的滚动条样式,可以通过 CSS 自定义滚动条外观来实现。以下是具体的方法: #### 使用自定义滚动条样式的解决方案 通过覆盖 `.el-table__body-wrapper` 类中的滚动条样式,可以调整其视觉效果。以下是一个完整的示例代码片段[^1]: ```css /* 定义滚动条轨道 */ .el-table__body-wrapper::-webkit-scrollbar-track { background-color: #f5f5f5; } /* 定义滚动条滑块 */ .el-table__body-wrapper::-webkit-scrollbar-thumb { background-color: #aaa; border-radius: 6px; } /* 鼠标悬停时改变滚动条颜色 */ .el-table__body-wrapper::-webkit-scrollbar-thumb:hover { background-color: #777; } /* 整体滚动条宽度 */ .el-table__body-wrapper::-webkit-scrollbar { width: 8px; /* 水平滚动条宽度 */ height: 8px; /* 垂直滚动条高度 */ } ``` 上述代码利用了 WebKit 浏览器支持的伪类 `-webkit-scrollbar` 来定制滚动条的不同部分。 #### 动态绑定滚动事件并控制行为 除了静态样式外,还可以动态监听滚动事件以增强用户体验。例如,在表格内容更新后自动滚动到底部的功能可通过如下方式实现[^2]: ```javascript import { ref, nextTick } from &#39;vue&#39;; const tableListRef = ref(null); // 更新数据后的回调函数 function updateDataAndScroll() { nextTick(() => { const tableBodyWrapper = tableListRef.value?.$el.querySelector( &#39;.el-table__body-wrapper&#39; ); if (tableBodyWrapper) { tableBodyWrapper.scrollTop = tableBodyWrapper.scrollHeight; } }); } ``` 此逻辑确保每次新增行或重新渲染列表时,都能让用户的视线聚焦于最新添加的数据上。 #### 注意事项 - 如果项目中有全局样式文件,则可以直接将上述 CSS 添加进去;否则建议将其作用范围限定在一个组件内部。 - 对于非 Webkit 内核浏览器(如 Firefox),需额外考虑兼容性问题,因为它们不完全支持这些特定前缀的选择器。 ```html <style scoped> /* Scoped styles only affect this component */ </style> ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值