页面表格高度自适应

前言

  • 现在后端管理系统主页面基本都是由三部分组成
    • 查询条件,高度不固定,可能有的页面查询条件多,有的少
    • 表格,高度不固定,占据页面剩余高度
    • 分页,高度固定
  • 这三部分加起来肯定是占满全屏的,那么我们可以结合flex布局,来实现。

方法一:利用flex布局

代码及效果

app.vue

  • 相当于页面首页
<template>
	<div id="app">
		<!-- 假设为页头内容,导航等...-->
		<div class="routers">
			<router-link :to="item.path" v-for="item in routerLinks" :key="item.name">{{ item.name }}</router-link>
		</div>
		<!-- 内容区域 -->
		<div class="content">
			<router-view />
		</div>
	</div>
</template>
<script>
export default {
	data() {
		return {
			routerLinks: [],
		};
	},
	created() {
		this.handleRouterLink();
	},
	methods: {
		handleRouterLink() {
			// 获取所有路由配置
			this.routerLinks = this.$router.getRoutes();
		},
	},
};
</script>

<style lang="scss" scoped>
#app {
	height: 100vh;
	display: flex;
	flex-direction: column;
}
.routers {
	display: flex;
	justify-content: space-around;
}
/* 确定内容高度,好让业务组件的 height:100%生效 */
.content {
	flex: 1;
}
</style>

test.vue

  • 某业务表格组件
<!-- 表格高度自适应 -->
<template>
	<div class="wrapper">
		<!-- 查询条件 -->
		<div class="searchView">
			<div class="formItem" v-for="(item, index) in formNum" :key="index"></div>
		</div>
		<!-- 表格 -->
		<div class="tableView" :key="tableKey">
			<el-table :data="tableData" ref="myTable" style="width: 100%" :height="tableHeight">
				<el-table-column prop="date" label="日期" width="180"> </el-table-column>
				<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
				<el-table-column prop="address" label="地址"> </el-table-column>
			</el-table>
		</div>
		<!-- 分页 -->
		<div class="pageView">
			<el-pagination
				:pager-count="5"
				@size-change="handleSizeChange"
				@current-change="handleCurrentChange"
				:current-page.sync="currentPage2"
				:page-sizes="[100, 200, 300, 400]"
				:page-size="100"
				layout="sizes, prev, pager, next"
				:total="1000"
			>
			</el-pagination>
		</div>
	</div>
</template>
<script>
export default {
	data() {
		return {
			// 表格key,当表格height变化时,el-table无法重新渲染,只能刷新key,强制渲染表格组件
			tableKey: 0,

			// 当前页数
			currentPage2: 1,

			// 查询条件数量
			formNum: 4,

			// 表格高度
			tableHeight: 500,

			// 表格数据
			tableData: [
				{
					date: '2016-05-02',
					name: '王小虎',
					address: '上海市普陀区金沙江路 1518 弄',
				},
				{
					date: '2016-05-04',
					name: '王小虎',
					address: '上海市普陀区金沙江路 1517 弄',
				},
				{
					date: '2016-05-01',
					name: '王小虎',
					address: '上海市普陀区金沙江路 1519 弄',
				},
				{
					date: '2016-05-03',
					name: '王小虎',
					address: '上海市普陀区金沙江路 1516 弄',
				},
			],
		};
	},

	async mounted() {
		this.handleTableHeight();

        // 当浏览器大小修改时,同时动态修改表格高度
		window.onresize = this.getDebounce(this.handleTableHeight, 500);
	},
	methods: {
		// 处理表格高度修改事件
		async handleTableHeight() {
			this.tableHeight = 0;
			await this.$nextTick();
			const tableView = document.querySelector('.tableView');
			this.tableHeight = tableView.clientHeight;
			console.log('tableHeight', this.tableHeight);
			this.tableKey++;
		},

		handleSizeChange(val) {
			console.log(`每页 ${val}`);
		},
		handleCurrentChange(val) {
			console.log(`当前页: ${val}`);
		},

		// 生成一个debounce函数,避免事件频繁除法
		getDebounce(func, delay) {
			let timer = null;
			return function (...args) {
				if (timer) {
					clearTimeout(timer);
				}
				timer = setTimeout(() => {
					func.apply(this, args);
				}, delay);
			};
		},
	},
};
</script>
<style lang="scss" scoped>
/* 以下样式皆可写到全局文件中,每个页面布局基本一致 */
.wrapper {
	display: flex;
	flex-direction: column;
	height: 100%;
	.searchView {
		display: flex;
		flex-wrap: wrap;
		gap: 10px 20px;
		.formItem {
			width: 230px;
			height: 30px;
			border: 1px solid #000;
		}
	}

	.tableView {
		flex: 1;
	}
}
</style>

效果

在这里插入图片描述

思路

  • 首先整个内容主页面.wrapper肯定是flex,并且纵向布局,高度100%。
  • 其次,我们要分别在查询条件、表格、分页外层套一层div,这样好进行样式管理。
  • 内容主页面肯定主要展示的是表格,那么我们就给表格外层的divtableView设置flex: 1;,占据剩余所有高度
  • 当页面加载完成的时候,由于是flex布局,表格的高度(剩余高度)就是wrapper的高度100% - searchView的高度 - pageView的高度
  • 然后我们在mounted钩子函数中,获取.tableViewdiv的clientHeight高度,这个值,就能作为表格的高度了。
  • 最后我们把这个高度值赋值给表格el-table的height属性,并且刷新key,强制表格重新渲染以达到效果。
  • 最最后,我们给window.onresize绑定了事件,并且优化了使用防抖,当浏览器大小修改的时候,页面也会动态自适应高度。

方法二:父元素高度-所有子元素高度

  • 要实现该方法,首先表格所在元素的父元素必须定高,固定px,或百分比都可(有效就行)

思路

  1. 首先表格要提取出来组件,这样获取表格本身元素直接使用this.$el(vue中)即可。
  2. 使用this.$el.parentElement获取表格父元素
  3. 然后再使用父元素中children属性,即可获取表格所有子元素的高度
  4. 最后表格高度 = 剩余空间高度 = 父元素高度-所有子元素高度

代码与效果

util.js

首先我们要先写一个工具函数,获取一个元素的总高度 = 上下外边距+上下内边距+上下边框宽度+元素内容高度

export const getElementTotalHeight = (element) => {
  // 获取元素样式
  const style = window.getComputedStyle(element);

  // 获取上下外边距,并转换成数字
  const marginTop = parseInt(style.marginTop, 10) || 0;
  const marginBottom = parseInt(style.marginBottom, 10) || 0;

  // 计算总高度:元素自身高度 + 元素上下内边距+上下边框宽度 + 上下外边距
  return element.offsetHeight + marginTop + marginBottom;
};

MyTable组件

  • mounted钩子函数时要自动计算可用高度,并且赋值给tableHeight属性,并且表格有上下10px的外边距
<template>
  <div class="my-table" :style="{ height: tableHeight + 'px' }">表格组件</div>
</template>
<script>
import { getElementTotalHeight } from "@/utils/util";

export default {
  data() {
    return {
      tableHeight: 0,
    };
  },
  mounted() {
    this.calcHeight();

    // 这里当屏幕比例发生变化时,自动调用
    window.addEventListener("resize", this.calcHeight);
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.calcHeight);
  },
  methods: {
    // 计算 组件可用高度
    calcHeight() {
      const parent = this.$el.parentElement;

      // 父组件高度
      const parentHeight = parent.clientHeight;
      // 父组件其他元素总高度
      const childrenHeights = Array.from(parent.children).reduce(
        (acc, child) => {
          // 排除掉组件本身
          if (child == this.$el) {
            return acc;
          }

          return acc + getElementTotalHeight(child);
        },
        0
      );

      // 本身的外边距
      const style = window.getComputedStyle(this.$el);
      const myMarginTop = parseInt(style.marginTop, 10) || 0;
      const myMarginBottom = parseInt(style.marginBottom, 10) || 0;

      this.tableHeight =
        parentHeight - childrenHeights - myMarginTop - myMarginBottom;
    },
  },
};
</script>
<style lang="scss" scoped>
.my-table {
  outline: 2px solid #000;
  width: 100%;
  margin: 10px 0;
  background-color: cornflowerblue;
}
</style>

主页面组件

  • 这里最外层使用了flex布局,重点是MyTable组件的父组件content使用了flex: 1;来定高
<template>
  <div class="test1">
    <div class="header">页面header导航</div>
    <div class="content">
      <div class="search">查询条件内容</div>

      <MyTable />

      <div class="pagination">分页内容</div>
    </div>
  </div>
</template>
<script>
import MyTable from "@/components/MyTable.vue";

export default {
  components: {
    MyTable,
  },
};
</script>
<style lang="scss" scoped>
.test1 {
  height: 80vh;
  width: 70vw;
  border: 1px solid red;
  display: flex;
  flex-direction: column;
}

.header {
  height: 10vh;
  width: 100%;
  background-color: darkgray;
}

.content {
  flex: 1;
}

.search {
  height: 10vh;
  width: 100%;
  background-color: aquamarine;
}

.pagination {
  height: 7vh;
  width: 100%;
  background-color: bisque;
}
</style>

效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值