ant design vue 多个Tabs 标签页 下使用 table组件滚动加载的坑 【第一个tab页可以滚动加载而切换第2 个tab不能触发】
在ant design vue 的使用中总会遇到一些坑,如标题所言,这里提供一个解决方法参考用
关键代码如下:
注:这里的table组件不要通过使用 ant 中封装的 scroll属性来达到超出高度显示滚动条的目的,而是自己定义一个内联样式:overflow-y:auto;height: 【某固定高度】px;
html:
js:
记得页面销毁前需要移除滚动
备注:下图的写法不可用
备注:ant design vue 的tab标签页的activeKey 必须是String类型,否则可能会出现初始化页面时候tab页无内容,点击后才会有内容以及上述组件中给table绑定滚动事件报错【没有这个dom】等情况
完整的组件代码如下:
<template> <div class="session-group"> <a-tabs v-model="activeKey" @change="callback"> <a-tab-pane key="1" tab="会话"> <a-table ref="session" id="session" :row-key="(record) => record.id" :columns="sessionColumns" :data-source="sessionData" :pagination="false" style="overflow-y: auto; height: 340px; padding-right: 3px" :loading="isLoading" > </a-table> </a-tab-pane> <a-tab-pane key="2" tab="群组" force-render> <a-table ref="group" id="group" :row-key="(record) => record.id" :columns="sessionColumns" :data-source="groupData" :pagination="false" :loading="isLoading" style="overflow-y: auto; height: 340px; padding-right: 3px" > </a-table> </a-tab-pane> </a-tabs> </div> </template> <script> import { getAction } from '@api/manage' export default { data() { return { activeKey: '1', timer: null, sessionFirstTime: 0, //session tab触底次数 groupFirstTime: 0, //group tab触底次数 isLoading: false, sessionPageNo: 1, groupPageNo: 1, scrollHeight: 0, tableHeader: 'table-header', sessionColumns: [ { title: '会话ID', dataIndex: 'id', key: 'id', scopedSlots: { customRender: 'id' }, align: 'center', }, { title: '机器ID', dataIndex: 'robotUserId', key: 'robotUserId', rowClassName: 'table-header', align: 'center', }, { title: '所属平台', dataIndex: 'resourceType_dictText', key: 'resourceType_dictText', ellipsis: true, rowClassName: 'table-header', align: 'center', }, { title: '会话状态', dataIndex: 'activeStatus_dictText', key: 'activeStatus_dictText', rowClassName: 'table-header', align: 'center', customRender: (text, row, index) => { if (text == '活跃') { return <span style="color:#2DBD6D">{text}</span> } else { return <span style="color:#F17E03">{text}</span> } }, }, ], sessionData: [], groupData: [], url: { session: '/robot/robotChat/getActiveSessionPlanelist', group: 'robot/robotChat/getActiveGroupSessionPlanelist', }, } }, mounted() { this.handleScroll() this.initSessionData() this.initGroupData() this.callback('1') this.timer = setInterval(() => { this.sessionPageNo = 1 this.groupPageNo = 1 this.sessionFirstTime = 0 this.groupFirstTime = 0 this.initSessionData() this.initGroupData() }, 30000) }, methods: { tabClick(key){ this.activeKey = key }, handleScroll() { document.getElementById('session').addEventListener('scroll', this.sessionFunction) }, sessionFunction() { var dd = document.querySelector('#session').scrollTop var ss = document.querySelector('#session').scrollHeight let hh = document.querySelector('#session').clientHeight if (ss - dd - hh <= 0) { this.sessionFirstTime++ this.loadMoreSession(this.sessionPageNo) } }, groupFunction() { var dd = document.querySelector('#group').scrollTop var ss = document.querySelector('#group').scrollHeight let hh = document.querySelector('#group').clientHeight if (ss - dd - hh == 0) { this.groupFirstTime++ this.loadMoreGroup(this.groupPageNo) } }, callback(key) { if (key == 2) { this.$nextTick(function () { document.getElementById('group').addEventListener('scroll', this.groupFunction) }) } this.activeKey = key this.$emit('currentKey', key) }, initSessionData() { this.isLoading = true var params = {} getAction(this.url.session, params) .then((res) => { // debugger if (res.success) { this.sessionData = res.result.records if (res.result.records.length > 0) { this.sessionPageNo++ } } else { this.$message.warning(res.message) } }) .catch((error) => { this.$message.error(error) }) this.isLoading = false }, initGroupData() { this.isLoading = true let obj = { isGroup: 1 } getAction(this.url.group, obj) .then((res) => { if (res.success) { this.groupData = res.result.records if (res.result.records.length > 0) { this.groupPageNo++ } } else { this.$message.warning(res.message) } }) .catch((error) => { this.$message.error(error) }) this.isLoading = false }, /* *滚动加载更多--会话 */ loadMoreSession(pageNo) { var params = { pageNo, } getAction(this.url.session, params) .then((res) => { if (res.success) { if (res.result.records.length > 0) { this.sessionData = [...this.sessionData, ...res.result.records] this.sessionPageNo++ } } else { this.$message.warning(res.message) } }) .catch((error) => { this.$message.error(error) }) this.isLoading = false }, /* *滚动加载更多--群组 */ loadMoreGroup(pageNo) { this.isLoading = true let obj = { isGroup: 1, pageNo } getAction(this.url.group, obj) .then((res) => { if (res.success) { if(res.result.records.length>0){ this.groupData = [...this.groupData, ...res.result.records] this.groupPageNo++ } } else { this.$message.warning(res.message) } }) .catch((error) => { this.$message.error(error) }) this.isLoading = false }, }, destroyed() {
window.removeEventListener('scroll', this.sessionFunction)
window.removeEventListener('scroll', this.groupFunction)
clearInterval(this.timer) this.timer = null }, } </script> <style lang="less" scoped> .session-group { height: 100%; /deep/ .ant-table-thead { background: linear-gradient(90deg, #d1dffc 0%, #e8effd 100%); } /deep/ .ant-table-thead > tr > th { background: transparent !important; } /*隐藏表格的表头的滚动条*/ /deep/ .ant-table-hide-scrollbar { overflow-y: hidden; overflow: hidden !important; margin-bottom: 0; padding-right: 0; } /deep/ .ant-tabs-tab { font-size: 16px; font-family: Microsoft YaHei; font-weight: bold; color: #606266; } /deep/ .ant-tabs-tab-active { color: #3e7efc; } /deep/ .ant-table-column-title { font-size: 14px; font-family: Microsoft YaHei; font-weight: bold; color: #58647b; } /deep/ .ant-table-tbody > tr > td { font-size: 14px; font-family: Microsoft YaHei; font-weight: 400; color: #606266; } /*滚动条样式-开始*/ ::-webkit-scrollbar { width: 6px; margin-left: 2px; } /*定义滚动条轨道 内阴影+圆角*/ ::-webkit-scrollbar-track { border-radius: 4px; background: #f1f4fa; margin-left: 2px; } /*定义滑块 内阴影+圆角*/ ::-webkit-scrollbar-thumb { border-radius: 4px; -webkit-box-shadow: inset 0 0 6px rgba(26, 25, 25, 0.3); background-color: rgba(0, 0, 0, 0.1); } /*滚动条样式-结束*/ /deep/ .ant-table-tbody .ant-table-row:nth-child(2n) { background: rgba(229, 237, 253, 0.4); } /deep/ .ant-table-tbody > tr > td { border-bottom: none; } } </style>
上述中对滚动事件的dom操作写法的调整:其实就是通过ref来获取元素,绑定事件
1、对元素绑定滚动事件:this.$refs.session.addEventListener('scroll', this.sessionFunction) 2、对元素移除滚动事件:this.$refs.session.removeEventListener('scroll', this.sessionFunction) 3、获取 内容顶部距离容器顶部的高度【被隐藏在内容区域上方的像素数】:this.$refs.session.scrollTop 4、获取内容的总高度【在没有滚动条的情况下,元素内容的实际总高度】:this.$refs.session.scrollHeight 5、获取可视区高度【可视区高度 + padding】:this.$refs.session.clientHeight