Vue2+el-table实现表格行上下滚动,表格单元格内容溢出左右滚动 TextScroll、TableWrapper

devtools/2024/11/27 21:56:29/

Vue2+el-table实现表格行上下滚动表格单元格内容溢出左右滚动 TextScroll、TableWrapper

TextScroll 文本左右滚动容器组件

<template><div ref="wrapper" class="scroll-wrapper" @mouseenter="mouseenter" @mouseleave="mouseleave"><div ref="text" class="text" :style="{transform: `translateX(${translateX}px)`}"><slot>{{ text }}</slot></div></div>
</template><script>javascript">
/*** 文本左右滚动容器组件*/
export default {name: 'TextScroll',props: {text: [String, Number],step: {type: [String, Number],default: 0.2}},data() {return {translateX: 0,trip: 0,realStep: 1,frameId: null}},mounted() {const rect = this.$refs.text.getBoundingClientRect()const wrapperRect = this.$refs.wrapper.getBoundingClientRect()this.trip = rect.right - wrapperRect.width - rect.leftthis.mouseleave()this.$emit('hook:beforeDestroy', () => {this.mouseenter()})},methods: {mouseenter() {window.cancelAnimationFrame(this.frameId)},mouseleave() {if (this.trip > 8) {this.frameId = window.requestAnimationFrame(this.animate)}},animate() {if (Math.abs(this.translateX) >= this.trip) {this.realStep = this.step}if (this.translateX >= 0) {this.realStep = this.step * -1}this.translateX += this.realStepthis.frameId = window.requestAnimationFrame(this.animate)}}
}
</script><style lang="scss" scoped>
.scroll-wrapper {overflow: hidden;.text {padding: 0 4px;display: inline-block;white-space: nowrap;}
}
</style>

TableWrapper 表格上下滚动容器组件

  • columns:表格列配置属性
    Eg. [{ label: '表头', prop: 'name', formatter: (content,row)=>content style: { width: '160px' } }]
  • data:表格配置数据
    Eg.[{ name: '父类', child: [{name: '子类0'}] }]
  • full:表格在容器内平铺展示
  • tdspace:表格边框是否分隔
  • expand:是否开启子行
  • step:行上下滚动补偿
<template><div :class="['table-wrapper',{full:full}]"><table><thead><tr><th v-for="(column,index) in columns" :key="index" :class="`th-${index}`":style="Object.assign({},column.style||{},column.headStyle||{})">{{ column.label }}</th></tr></thead></table><el-scrollbar ref="scroll"><table v-if="data.length" :class="['table-body',{'td-space':tdspace}]":style="{transform: `translateY(${translateY}px)`}" @mouseenter="mouseenter"@mouseleave="mouseleave"><tbody><template v-for="(item,key) in data"><tr :key="key" :class="[`tr-${key}`, `border-${item.key}`]":style="{cursor: expand?'pointer':'auto'}" @click="doExpand(item.key)"><template v-for="(column,index) in columns"><td v-if="column.type === 'index'" :key="`${key}-${index}`" :class="`td-${index}`":style="column.style||{}">{{ key+1 }}</td><td v-else :key="`${key}-${index}`" :class="`td-${index}`":style="column.style||{}"><TextScroll:text="column.formatter?column.formatter(item[column.prop],item):item[column.prop]" /></td></template></tr><template v-if="item.child && expandKey[item.key]"><tr v-for="(v,i) in item.child" :key="`${item.key}-${i}`":class="[`tr-${key+i+1}`,`border-${item.key}`]" class="child"><template v-for="(column,index) in columns"><td v-if="column.type === 'index'" :key="`${key+i+1}-${index}`":class="`td-${index}`" :style="column.style||{}">{{ i+1 }}</td><td v-else :key="`${key+i+1}-${index}`" :class="`td-${index}`":style="column.style||{}"><TextScroll:text="column.formatter?column.formatter(v[column.prop],v):v[column.prop]" /></td></template></tr></template></template></tbody></table><div v-else class="empty">暂无数据</div></el-scrollbar></div>
</template><script>javascript">
/*** 列表*/
import TextScroll from './TextScroll.vue'
export default {name: 'TablerWrapper',components: {TextScroll},props: {/* 表格配置列属性 */columns: Array,/* 表格配置数据 */data: Array,/* 数据不滚动,进行平铺展示 */full: Boolean,/* 表格边框是否分隔 */tdspace: {type: Boolean,default: false},/* 是否开启表格子行 */expand: Boolean,/* 行自动上下滚动补偿 */step: {type: [String, Number],default: 0.3}},data() {return {translateY: 0,staticTranslateY: 0,trip: 0,realStep: 1,frameId: null,expandKey: {}}},watch: {data(n) {if (n.length) {this.expandKey = this.data.reduce((s, v) => {s[v.key] = truereturn s}, {})this.$nextTick(() => {this.initScroll()this.mouseleave()})}}},methods: {initScroll() {window.cancelAnimationFrame(this.frameId)const rect = this.$refs.scroll.$el.querySelector('.table-body').getBoundingClientRect()const wrapperRect = this.$refs.scroll.$el.querySelector('.el-scrollbar__view').getBoundingClientRect()this.trip = rect.bottom - wrapperRect.height - rect.top},mouseenter() {window.cancelAnimationFrame(this.frameId)const translateY = this.translateYthis.translateY = 0this.$nextTick(() => {this.$refs.scroll.$el.querySelector('.el-scrollbar__wrap').scrollTop = Math.abs(translateY)})},mouseleave() {const translateY = this.$refs.scroll.$el.querySelector('.el-scrollbar__wrap').scrollTopthis.$refs.scroll.$el.querySelector('.el-scrollbar__wrap').scrollTop = 0this.translateY = translateY * -1if (this.trip > 8) {this.frameId = window.requestAnimationFrame(this.animate)}},animate() {if (Math.abs(this.translateY) >= this.trip) {this.realStep = this.step}if (this.translateY >= 0) {this.realStep = this.step * -1}this.translateY += this.realStepthis.frameId = window.requestAnimationFrame(this.animate)},doExpand(key) {this.expandKey = { ...this.expandKey, [key]: !this.expandKey[key] }this.$nextTick(() => {this.initScroll()})}}
}
</script><style lang="scss" scoped>
.table-wrapper {color: #fff;display: flex;flex-direction: column;flex: 1;overflow: hidden;table {table-layout: fixed;border-collapse: separate;border-spacing: 0 3px;width: 100%;thead th {font-size: 14px;text-align: center;vertical-align: bottom;padding: 10px 5px;background: rgba(69, 167, 248, 0.2980392156862745);}td {color: #fff;font-size: 18px;padding: 6px 6px;text-align: center;line-height: 16px;vertical-align: middle;background: rgba(69, 167, 248, 0.09803921568627451);}.child {td {background: rgba(60, 165, 250, 0.298);}}td,th {&:first-child {border-radius: 4px 0 0 4px;}&:last-child {border-radius: 0 4px 4px 0;}}}.table-body.td-space {border-collapse: separate;border-spacing: 3px 3px;}.el-scrollbar {position: relative;flex: 1;overflow: hidden;}
}
.full {::v-deep .el-scrollbar__view {height: 100%;}.table-body {min-height: 100%;td {vertical-align: middle;}}
}
.empty {position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);text-align: center;font-size: 12px;
}
</style>

http://www.ppmy.cn/devtools/137492.html

相关文章

【Mybatis】动态SQL详解

文章目录 动态SQLifsetifwhereiftrimforeachchoosesql 动态SQL <if> 用于条件判断&#xff0c;决定是否包含某个SQL片段。 ifset <set> 用于动态生成 SET 子句&#xff0c;自动处理多余的逗号。 <!-- 更新用户信息 --> <update id"edit" &g…

自定义 RouterLink 组件 v-slot custom

高级自定义&#xff1a;通过 v-slot 使用插槽 API 如果你需要更复杂的自定义逻辑或更加灵活的渲染&#xff0c;可以结合 v-slot 来实现&#xff1a; <template><router-link :to"to" custom v-slot"{ navigate }"><div click"navigat…

【git】取消一个已提交的文件或路径的追踪

在 Git 中&#xff0c;如果想取消对一个已提交的文件或路径的追踪&#xff0c;有几种方法可以实现这一点&#xff0c;具体取决于实际场景。以下是几种常见的方法&#xff1a; 1. 从索引中移除文件&#xff08;暂存区&#xff09; 如果只是希望取消对某个文件的追踪&#xff0…

极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【一】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…

VirtIO实现原理之数据结构与数据传输演示(2)

接前一篇文章:VirtIO实现原理之数据结构与数据传输演示(1) 本文内容参考: VirtIO实现原理——vring数据结构-CSDN博客 VirtIO实现原理——数据传输演示-CSDN博客 特此致谢! 一、数据结构总览 2. 相关数据结构 上一回读了《Virtual I/O Device (VIRTIO) Version 1.3》…

Cesium教程03_加载b3dm高度

使用 Vue3 和 Cesium 构建三维地球场景并实现高度调整功能 引言 在现代 Web GIS&#xff08;地理信息系统&#xff09;开发中&#xff0c;Cesium 是一款功能强大的三维地球可视化工具。本文展示了如何使用 Vue3 与 Cesium 集成&#xff0c;实现一个支持调整高度功能的三维地球…

OSPF路由状态数据库、type 类型、完整的LSA

【OSPF】 1.Lsdb&#xff1a;链路状态数据库【存放多条LSA——链路状态通告信息】 2..Dis ospf lsdb : 查看设备LSDB. 3.Ospf process__ with router ID __ &#xff1a; ospf的进程为___router_id为 ____. 4.Lsdb&#xff1a;链路状态数据库【存放多条…

R和Julia免疫细胞映射到组织切片

将免疫细胞映射到组织切片是一种整合多种技术的高精度方法&#xff0c;用于揭示细胞在组织微环境中的空间分布。通过使用如空间转录组学、免疫荧光染色或单细胞RNA测序等技术&#xff0c;科学家可以精确定位特定免疫细胞类型&#xff0c;并分析它们与组织结构或病理学变化的关联…