我们前端开发人员在使用表格的过程中,大概率碰到的都是表格头部在表格的最上边,然后呈一行展示,紧接着就是表格的每一行的每一个单元格来展示具体内容的场景,很少会遇到表格的头部呈纵向一行展示,也就是说表格的头部在左边,具体的内容在右边(也可以说是左右结构)这种使用场景,而且有时候的场景可能会是纵向表头有两列或多列。

遇到这样的需求或者说使用场景,你也不能说人家产品提的需求不合理,毕竟使用场景不同。我不知道咱们同行的前端大佬是用啥牛逼格拉斯的技术来实现这样的需求的,反正我以前基本都是直接上一个表格,然后各种tr、td的往上堆,如果需要展示的多了,最后会发现整个页面上基本全是各种tr、td的标签,Level Low就不说了,关键是看着闹心、烦心外加恶心。

最近想着说再遇到这样的需求,可不能再各种tr、td往上堆了,恰好近期的需求开发上也有这样的使用场景,索性就动动脑筋自己封装一个吧,以后用起来也方便,也能提高开发效率,界面看起来也能清爽不少。

一开始搞的时候,确实没头绪,很懵圈。上网搜了一把,想着说看看能不能找点灵感,或者说有好的例子能借鉴一下,结果一圈下来,发现就算是有人搞过这样的封装,也是感觉词不达意,说好的封装呢?有人基于elementUI就实现了一列纵向表头的封装,有人基于索引实现了两列纵向表头的封装,但代码中出现的各种数字令人费解,不利于扩展。

算了,还是自己想办法吧。不有句话说的好嘛:“人的脑洞有多大,就能实现多牛逼的需求。”于是,对着设计稿上这样的表格,我是左看右看,上看下看,后来突然想到我们经常使用的表单组件,大概率不就是左右结构嘛,基于这个我又想到曾经在封装Vue Element的form表单组件的时候还使用过分段的思想,现在把这个分段的思想用在这里不正好吗?

办法总比困难多,这句老俗语总结的真是太TMD的完全正确了!

照例先上一张效果图:



1、封装的纵向表头表格组件Table.vue

<template>
<table class="portait-table" border="1" cellspacing="0" cellpadding="0">
<tr v-for="(row, i) in columns" :key="i">
<template v-for="x in row">
<TD :config="x" :data="data" />
</template>
</tr>
</table>
</template> <script>
import * as Components from '@/components/table/cell/components'
import { chunk } from '@/utils'
import { noop } from '@/common/constant' export default {
props: {config: Object},
data() {
const {headers, data, rowSize = 2} = this.config || {}
return {
headers,
data,
rowSize,
};
},
computed: {
columns: ({headers, rowSize}) => chunk(headers, rowSize)
},
components: {
TD: {
functional: true,
props: {config: Object, data: Object},
render: (h, {props: {config, data}}) => {
let {type = 'Default', label, prop} = config, value = data[prop], isEmpty = value === '' || value === undefined || value === null, children = noop if(label && isEmpty) children = h(Components.Default, {props: {value: '-'}})
else children = h(Components[type], {props: {value, data, ...config}}) return [h('td', label), h('td', [children])]
}
}
},
mounted(){
const {columns} = this, last = columns[columns.length - 1], lastTwo = columns[columns.length - 2]
for(let i = 0; i < (lastTwo.length - last.length); i++){
this.headers.push({prop: '', label: ''})
}
},
}
</script> <style lang="scss" scoped>
.portait-table{
border-collapse: collapse;
border: none;
width:100%;
td {
border: 1px solid #F3F3F3;
height: 40px;
padding-left: 10px;
color:#333;
&:nth-child(odd){
background: #EAEAEA;
color: #454545;
}
}
}
</style>

对于以上组件中的代码,需要做一些以下说明。

2、分段工具的实现chunk

export const chunk = (arr, size) => {
if(!arr.length || size < 1) return [];
let list = [], index = 0, resIndex = 0, len = arr.length;
while (index < len) {
list[resIndex++] = arr.slice(index, index += size);
}
return list;
}

数组被分段后的效果,你可以自己打印出来看看就明白了。

3、封装的组件中引入了一些其他的组件是干嘛使的呢?比如:

import * as Components from '@/components/table/cell/components'

引入这些组件,主要是为了对一些特殊的字段值进行特殊的处理,比如金额千分位、时间戳格式化、枚举(映射)等,这些组件的具体代码和介绍在我的这篇博文封装Vue Element的table表格组件中有具体的描述,您可以摆驾过去上上眼。

4、代码中的render函数,这里也不再赘述,我之前的博文中都有介绍,你也可以自己去看vue的API或查阅其他资料。

5、在封装的组件的mounted生命周期里有这样一段代码:

const {columns} = this, last = columns[columns.length - 1], lastTwo = columns[columns.length - 2]
for(let i = 0; i < (lastTwo.length - last.length); i++){
this.headers.push({prop: '', label: ''})
}

这段代码是干嘛滴的呢?我们都知道,像这样的纵向表头左右结构展示的表格,不管你分了几列表头(只有一列表头的除外)展示,都有可能在表格的最后一行出现不完整的情况,也就是说可能会在整个表格的右下角出现空缺的情况,如下图:



这种类似表格残缺不全的情况当然是不被允许的,mounted生命周期中的那段代码就是用来补这个缺的。其原理就是拿分段后的最后一个数组长度与倒数第二个数组长度进行比较,如果两者不相等,则最后一个数组长度比倒数第二个数组长度少了几个,就在headers数组的最后push几个属性值是空的的对象,最后再利用计算属性去重新分段(组件中的计算属性会被执行两次,第一次是初始分段,第二次是补缺后的再次分段),就达到了本文开头展示的补缺后的效果图。

其实,代码中真正补缺的原理可能与我描述的实现不太一样,比如代码中并没有拿分段后的最后一个数组长度与倒数第二个数组长度进行比较,而是用了一个for循环就搞定了,因为for循环也有自己的判断嘛,但是原理真的差不离。

6、至于那个noop,它其实就是定义了一个能返回空对象的函数export const noop = () => {},它在封装中的作用就是用来初始化函数。还有那个rowSize,是用来设置分成几段的,默认是2段。

7、封装时用到了computed计算属性,这个属性想必大家已经很熟了,这里再多说一句吧:计算属性的key的值是一个函数,其参数是Vue的实例化this对象。为啥这里要强调这一点呢,是因为知道了这一点,我们就可以在其函数的参数中直接解构this了,比如:

computed: {
columns: ({headers, rowSize}) => chunk(headers, rowSize)
},

而我们平时常用的写法是:

computed: {
columns(){
const {headers, rowSize} = this
return chunk(headers, rowSize)
}
},

两厢对比,哪种写法更优雅、性能更高呢?当然是前者了。

8、使用封装后的表格Table组件

<template>
<Table :config="config" />
</template> <script>
import Table from '@/components/Table' export default {
components: {
Table
},
data(){
return {
config: {
headers: [
{prop: 'ruleName', label: '规则名称'},
{prop: 'money', label: '执行金额', type: 'Currency'},
{prop: 'fileName', label: '附件名称'},
{prop: 'ruleRiskLevel', label: '预警颜色'},
{prop: 'monitorResult', label: '监控结果', type: 'Enum', Enum: {name: 'monitor'}},
{prop: 'productCode', label: '产品系列'},
{prop: 'date', label: '执行时间', type: 'Date', format: 'yyyy-MM-dd'},
],
rowSize: 2,
data: {
ruleName: '股权质押',
money: 3256898,
fileName: '',
ruleRiskLevel: '红色',
monitorResult: '00',
productCode: '事业部',
date: new Date().getTime(),
}
}
}
},
}
</script>

本文到此,基本就实现了纵向表头的table表格封装,想展示几列表头,就把rowSize设置成几就可以了,非常方便。

封装Vue纵向表头左右结构的table表格的更多相关文章

  1. Vue + Element-ui实现后台管理系统(5)---封装一个Form表单组件和Table表格组件

    封装一个Form表单组件和Table组件 有关后台管理系统之前写过四遍博客,看这篇之前最好先看下这四篇博客.另外这里只展示关键部分代码,项目代码放在github上: mall-manage-syste ...

  2. 封装Vue Element的table表格组件

    上周分享了几篇关于React组件封装方面的博文,这周就来分享几篇关于Vue组件封装方面的博文,也好让大家能更好地了解React和Vue在组件封装方面的区别. 在封装Vue组件时,我依旧会交叉使用函数式 ...

  3. 封装Vue Element的可编辑table表格组件

    前一段时间,有博友在我那篇封装Vue Element的table表格组件的博文下边留言说有没有那种"表格行内编辑"的封装组件,我当时说我没有封装过这样的组件,因为一直以来在实际开发 ...

  4. element-ui的table表格控件表头与内容列不对齐问题

    原文链接:点我 element-ui的table表格控件表头与内容列不对齐问题 解决方法:将以下样式代码添加到index.html.或app.vue中(必须是入口文件,起全局作用!)body .el- ...

  5. asp.net table表格表头及列固定实现

    http://blog.csdn.net/zdw_wym/article/details/48630337 在开发中常会遇到table表格中列特别多,下拉后,表头就看不见了,水平滚动后,第1.2列就看 ...

  6. 封装Vue Element的form表单组件

    前两天封装了一个基于vue和Element的table表格组件,阅读的人还是很多的,看来大家都是很认同组件化.高复用这种开发模式的,毕竟开发效率高,代码优雅,逼格高嘛.虽然这两天我的心情很糟糕,就像& ...

  7. element-ul二次封装table表格

    在项目中el的表格使用的地方太多了,若不进行封装,使用的时候页面会显得非常的冗余且难以维护,有时表格样式还不能做到一致:今天分享一个在工作中封装的表格 由于大多代码都在页面有介绍,就不在外面解释了 一 ...

  8. 5种做法实现table表格中的斜线表头效果

    table表格,这个东西大家肯定都不陌生,代码中我们时常都能碰到,那么给table加一个斜线的表头有时是很有必要的,但是到底该怎么实现这种效果呢? 我总结了以下几种方法: 1.最最最简单的做法 直接去 ...

  9. js 实现table表格拖拽和点击表头升降序排序

    js 实现table表格拖拽和点击表头升降序排序,写的比较乱,用的时候可以把其中的一些模块函数提取出来 样式,由于是可拖拽表格,所以样式 table tr th{cursor:move;} js实现 ...

随机推荐

  1. 使用 Canvas 实现一个类似 Google 的可视化的页面错误反馈库

    使用 Canvas 实现一个类似 Google 的可视化的页面错误反馈库 iframe 嵌套 iframe iframe 包含 复制的 HTML 页面 和支持可以拖拽的工具栏 鼠标经过上面,智能识别 ...

  2. eyes protect app

    eyes protect app https://awaremac.com/

  3. Renice INC:全球经济危机持续,2021年红酒市场走向如何?

    2021年,全球经济危机仍在持续,很多国家的经济出现了严重的下滑,不得不以降低利率维持经济.那么,全球经济危机对于红酒市场有什么影响?2021年,红酒市场走势如何呢?近日,美国知名红酒公司伦尼斯公司对 ...

  4. HTTP 协议的前世今生

    尽人事,听天命.博主东南大学研究生在读,热爱健身和篮球,正在为两年后的秋招准备中,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 C ...

  5. Asp.Net Core学习笔记:(二)视图、模型、持久化、文件、错误处理、日志

    TagHelper 入门 优点:根据参数自动生成,不需要手写超链接,类似Django模板里面的url命令. 在ViewImport中添加TagHelper @addTagHelper *,Micros ...

  6. 简单梳理下 Vue3 的新特性

    在 Vue3 测试版刚刚发布的时候,我就学习了下 Composition API,但没想到正式版时隔一年多才出来,看了一下发现还是增加了不少新特性的,在这里我就将它们一一梳理一遍. 本文章只详细阐述 ...

  7. 简单比较 @EnableEurekaClient 和 @EnableDiscoveryClient 两个注解

    @EnableEurekaClient 和 @EnableDiscoveryClient 都是让eureka发现该服务并注册到eureka的注解 相同点: 它们都能让注册中心Eureka发现 , 并将 ...

  8. 解决springBoot上传大文件异常问题

    上传文件过大时的报错: org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size ex ...

  9. python爬虫模拟登录验证码解决方案

    [前言]几天研究验证码解决方案有三种吧.第一.手工输入,即保存图片后然后我们手工输入:第二.使用cookie,必须输入密码一次,获取cookie:第三.图像处理+深度学习方案,研究生也做相关课题,就用 ...

  10. Redis-第十章节-链表

    目录 数组和链表 链表 对比 总结 1.数组和链表 数组: 数组会在内存中开辟一块连续的空间存储数据,这种存储方式有利也有弊端.当获取数据的时候,直接通过下标值就可以获取到对应的元素,时间复杂度为O( ...