表格高度自适应
效果图:表格的高度是减去距离浏览器顶部的距离,在减去动态获取距离浏览器底部的距离,从而得到的高度
使用自定义指令来实现表格高度自适应
1、先新建src/directive/table文件夹,然后在table下创建adaptive.js。页面缩放的监听是使用的 element-ui
中的 resize-event
,将 addResizeListener
和 removeResizeListener
引入进来。
自定义指令要用到的钩子函数:
- bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
- unbind:只调用一次,指令与元素解绑时调用。
注意:
如果不需要动态获取底部距离,则修改为 const bottomOffset = (value && value.bottomOffset) || 0
需要动态获取底部距离则不需要改动代码
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
// 设置表格高度
const doResize = async (el, binding, vnode) => {
// 获取表格Dom对象
const { componentInstance: $table } = await vnode
// 获取调用传递过来的数据
const { value } = binding
if (!$table.height) {
throw new Error(`el-$table must set the height. Such as height='100px'`)
}
// 获取距底部距离(用于展示页码等信息)-------如果不需要动态减去底部距离,则使用这个
// const bottomOffset = (value && value.bottomOffset) || 0
// 修改组件中的 testValue 的值-------需要动态减去底部距离,使用这个
const bottomOffset = el.dataset.test
if (!$table) return
// 计算列表高度并设置
const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
$table.layout.setHeight(height)
$table.doLayout()
}
export default {
// 初始化设置---bind只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
bind (el, binding, vnode) {
// 设置resize监听方法
el.resizeListener = async () => {
await doResize(el, binding, vnode)
}
// 绑定监听方法到addResizeListener
addResizeListener(window.document.body, el.resizeListener)
},
// 绑定默认高度---inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
async inserted (el, binding, vnode) {
await doResize(el, binding, vnode)
},
// 销毁时设置---unbind:只调用一次,指令与元素解绑时调用。
unbind (el) {
// 移除resize监听
removeResizeListener(el, el.resizeListener)
}
}
2、绑定到vue中,在table下创建index.js
import adaptive from './adaptive'
const install = function (Vue) {
// 绑定v-adaptive指令
Vue.directive('adaptive', adaptive)
}
if (window.Vue) {
window['adaptive'] = adaptive
// eslint-disable-next-line no-undef
Vue.use(install)
}
adaptive.install = install
export default adaptive
3、全局注册
import adaptive from './directive/el-table'
Vue.use(adaptive)
4、在页面中使用
自定义尺寸,然后减去
<el-table
ref="table"
:data="tableData"
// 自定义指令,bottomOffset 代表距离底部的距离
v-adaptive="{bottomOffset: 85}"
// 高度属性,100无具体意义,仅为初始值,不可省略
height="100px"
>
。。。
</el-table>
动态获取表格下方元素的高度,然后减去该元素尺寸
<template>
<div>
<el-table
ref="table"
:data="tableData"
:height="tableHeight"
v-adaptive
:data-test="bottom"
>
。。。
</el-table>
</div>
</template>
<script>
export default {
props: {
bottom: {//表格距离浏览器底部的高度
type: Number,
default: 0
},
tableData: {//表格数据
type: Array,
default: []
},
},
data () {
return {
tableHeight: '0px',
};
},
mounted () {
// 根据浏览器高度设置初始高度,并监听浏览器高度变化,改变表格高度,50表示表格距离浏览器的高度
this.$nextTick(() => {
// 根据浏览器高度设置初始高度
this.$refs.table.$el.getBoundingClientRect().top //表格距离浏览器的高度
this.tableHeight = window.innerHeight - this.$refs.table.$el.getBoundingClientRect().top - 50//减掉头部任务栏高度
// 监听浏览器高度变化,修改表格高度
window.onresize = () => {
this.tableHeight = window.innerHeight - this.$refs.table.$el.getBoundingClientRect().top - 50
}
})
},
};
</script>
由于我是封装的,所以这里只贴了重要代码,详细代码在最后。
表格自动滚动,滚动到底部后从头开始
废话不多说,直接贴主要代码
created () {
setTimeout(() => {
if (this.animate) {
this.animatesgjl()
}
}, 0)
},
methods: {
// 表格自动滚动
animatesgjl () {
// 拿到表格挂载后的真实DOM
const table = this.$refs.table
// 拿到表格中承载数据的div元素
const divData = table.bodyWrapper
const clientHeight = this.$refs.table.$el.clientHeight - 48//减去表头
// 是否超过可视区,超过自动滚动,否则停留3秒跳转
if (clientHeight < divData.scrollHeight) {
// 拿到元素后,对元素进行定时增加距离顶部距离,实现滚动效果(此配置为每100毫秒移动1像素)
this.timer1 = setInterval(() => {
// 元素自增距离顶部1像素
divData.scrollTop += 2
// 判断元素是否滚动到底部(可视高度+距离顶部=整个高度)
if (clientHeight + divData.scrollTop == divData.scrollHeight) {
clearInterval(this.timer1)
this.$nextTick(() => {
this.animatesgjl()
})
// 重置table距离顶部距离
divData.scrollTop = 0
}
}, 100)
} else {
this.notimer1 = setInterval(() => {
clearInterval(this.notimer1)
this.animatesgjl()
}, 3000)
}
},
}
封装完整代码
<template>
<div style="width: 100%; height: 100%">
<el-table
ref="table"
:data="tableData"
style="width: 100%"
:height="tableHeight"
v-adaptive
:data-test="bottom"
>
<solt></solt>
</el-table>
</div>
</template>
<script>
/***
*
* :height是设置初始值,可以写成:height=‘100px’,
* 但是这样设置,获取表格高度的时候,就一直获取到的值是100px,而不是表格真正的高度
* (虽然elements控制台显示的是真正高度,但是一直获取不到,获取的都是100,就不是很理解)
* 所以我这里又重新在mounted中重新设置动态高度,这样后期在设置表格自动滚动的时候就可以获取到表格高度啦
*
*
* 自定义指令不需要动态减去底部距离则使用v-adaptive=“{bottomOffset:50}”
* 动态使用v-adaptive并使用dataset,
*/
export default {
props: {
bottom: {//表格距离浏览器底部的高度
type: Number,
default: 0
},
tableData: {//表格数据
type: Array,
default: []
},
animate: {//表格是否需要滚动
type: Boolean,
default: true
}
},
data () {
return {
tableHeight: '0px',
};
},
mounted () {
// 根据浏览器高度设置初始高度,并监听浏览器高度变化,改变表格高度,50表示表格距离浏览器的高度
this.$nextTick(() => {
// 根据浏览器高度设置初始高度
this.$refs.table.$el.getBoundingClientRect().top //表格距离浏览器的高度
this.tableHeight = window.innerHeight - this.$refs.table.$el.getBoundingClientRect().top - 50//减掉头部任务栏高度
// 监听浏览器高度变化,修改表格高度
window.onresize = () => {
this.tableHeight = window.innerHeight - this.$refs.table.$el.getBoundingClientRect().top - 50
}
})
},
created () {
setTimeout(() => {
if (this.animate) {
this.animatesgjl()
}
}, 0)
},
methods: {
// 表格自动滚动
animatesgjl () {
// 拿到表格挂载后的真实DOM
const table = this.$refs.table
// 拿到表格中承载数据的div元素
const divData = table.bodyWrapper
const clientHeight = this.$refs.table.$el.clientHeight - 48//减去表头
// 是否超过可视区,超过自动滚动,否则停留3秒跳转
if (clientHeight < divData.scrollHeight) {
// 拿到元素后,对元素进行定时增加距离顶部距离,实现滚动效果(此配置为每100毫秒移动1像素)
this.timer1 = setInterval(() => {
// 元素自增距离顶部1像素
divData.scrollTop += 2
// 判断元素是否滚动到底部(可视高度+距离顶部=整个高度)
if (clientHeight + divData.scrollTop == divData.scrollHeight) {
clearInterval(this.timer1)
this.$nextTick(() => {
this.animatesgjl()
})
// 重置table距离顶部距离
divData.scrollTop = 0
}
}, 100)
} else {
this.notimer1 = setInterval(() => {
clearInterval(this.notimer1)
this.animatesgjl()
}, 3000)
}
},
}
};
</script>
<style lang="scss" scoped>
</style>
页面调用组件的完整代码
<template>
<div ref="form" class="form">
<div ref="box1">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
<div>11</div>
</div>
<Table :bottom="bottom" :animate="false" :tableData="tableData1">
<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>
</Table>
<div ref="box">
<div>12</div>
<div>12</div>
<div>12</div>
<div>12</div>
<div>12</div>
<div>12</div>
<div>12</div>
<div>12</div>
</div>
</div>
</template>
<script>
import Table from "@/components/Table"
export default {
components: {
Table
},
data () {
return {
bottom: 0,
tableData1: [
{
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 弄",
},
{
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 弄",
},
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄",
},
{
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 弄",
},
{
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 弄",
},
],
}
},
created () {
},
mounted () {
this.$nextTick(() => {
this.bottom = this.$refs.box.offsetHeight
});
},
methods: {
},
}
</script>
<style scoped lang="scss">
.form {
width: 100%;
height: 100%;
// display: flex;
// flex-direction: column;
}
</style>
链接:https://pan.baidu.com/s/1NLG97swN7YaLbxKnxa_qWw
提取码:94i6