使用el-row、el-col制作表格及表格下方的展开/收起按钮
效果图如下
- 动态图
- 收起状态
- 展开状态
- 无数据状态
功能:
● 默认展示三行数据,超出三行的数据被折叠,点击展开按钮,即可展开
● 如果没有数据,展示内容为:暂无数据,且展开按钮也不显示
● 如果数据不到三行或者只有三行,那么展开按钮不显示
思路:
-
使用
el-row
、el-col
将表格的雏形可以先绘制出来el-col
中的span
将一行分为24份- 具体样式看下面的css代码
-
默认展示三行数据,超出三行的数据被折叠
- 将展示的数据放在一个数组中,使用
v-for
循环遍历 - 使用
v-show
判断index
是否小于3,⚠️ 这里不能使用v-if
,因为v-for
和v-if
不推荐同时使用
- 将展示的数据放在一个数组中,使用
-
展开与收起的实现
- 定义一个变量,定义为false,再定义一个方法监听这个值的改变,具体实现看代码
-
具体实现看代码
为什么v-if和v-for不推荐同时使用
v-for
指令基于一个数组来渲染一个列表v-for
指令基于一个数组来渲染一个列表v-for
比v-if
优先级高,所以使用的话,每次v-for
都会执行v-if
,造成不必要的计算,影响性能,尤其是当之需要渲染很小一部分的时候。
<template>
<div class="overview-system-state">
<div class="overview-system-state__row">
<div class="title">{{ labelInfo.title }}</div>
<div class="set action-link">{{ labelInfo.set }}</div>
</div>
<div class="overview-system-state__labels">
<el-row class="header">
<el-col :span="2">弱点数</el-col>
<el-col :span="2">风险数</el-col>
<el-col :span="6">分系统名称</el-col>
<el-col :span="8">分系统地址</el-col>
<el-col :span="3">系统风险指数</el-col>
<el-col :span="3">系统状态</el-col>
</el-row>
<div v-if="labelInfo.list.length !== 0">
<el-row
class="state-item"
justify="center"
v-for="(item, index) in labelInfo.list"
:key="index"
v-show="index < 3 || isOpen"
>
<el-col :span="2">
<span class="state-item__span">{{ item.weaknessCnt }}</span>
</el-col>
<el-col :span="2">
<span class="state-item__span">{{ item.riskCnt }}</span>
</el-col>
<el-col :span="6">
<span class="state-item__span">{{ item.subsystemName }}</span>
</el-col>
<el-col :span="8">
<span class="state-item__span">{{
item.subsystemIp
}}</span>
</el-col>
<el-col :span="3">
<span
class="status-item__top__wei"
:class="
'status-item__top__' + levelMap[item.riskExponent.riskLevel]
"
>
<qz-icon :class="levelMap[item.riskExponent.riskLevel]"></qz-icon>
<span>{{ item.riskExponent.count || 0 }}</span>
<qz-icon
v-if="item.riskExponent.exponentTrend !== 'mid'"
:class="
item.riskExponent.exponentTrend === 'up'
? 'add-color icon-jiantou-hong'
: 'decrease-color icon-jiantou-lv'
"
></qz-icon>
</span>
</el-col>
<el-col :span="3">
<div class="status-item__status">
<span :class="'status-item__status__' + stateMapEn[item.state]">{{
stateMap[item.state]
}}</span>
</div>
</el-col>
</el-row>
</div>
<el-row v-show="labelInfo.list.length <= 0" style="text-align: center">
暂无数据
</el-row>
</div>
<div class="overview-system-state__footer" v-if="labelInfo.list.length > 3">
<div class="overview-system-state__footer__item">
<div class="action-link" @click="handleOpen">
<span>{{ !isOpen ? "展开" : "收起" }}</span>
<qz-icon
:class="!isOpen ? 'icon-arrow-down-copy' : 'icon-arrow-up'"
style="font-size: 14px; padding-left: 5px"
></qz-icon>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isOpen: false,
stateMap: {
0: "异常",
1: "正常",
},
stateMapEn: {
0: "abnormal",
1: "normal",
},
levelMap: {
1: "icon-diwei",
2: "icon-zhongwei",
3: "icon-gaowei",
},
labelInfo: {
title: "分系统状态",
set: "设置",
list: [
{
weaknessCnt: 66,
riskCnt: 77,
subsystemName: 'Kylin',
subsystemIp: '192.168.1.102',
riskExponent: {
riskLevel: 1,
count: 25,
exponentTrend: 'up'
},
state: 0
},
{
weaknessCnt: 66,
riskCnt: 77,
subsystemName: 'Kylin',
subsystemIp: '192.168.1.102',
riskExponent: {
riskLevel: 2,
count: 25,
exponentTrend: 'down'
},
state: 1
},
{
weaknessCnt: 66,
riskCnt: 77,
subsystemName: 'Kylin',
subsystemIp: '192.168.1.102',
riskExponent: {
riskLevel: 3,
count: 25,
exponentTrend: 'up'
},
state: 1
},
{
weaknessCnt: 66,
riskCnt: 77,
subsystemName: 'Kylin',
subsystemIp: '192.168.1.102',
riskExponent: {
riskLevel: 1,
count: 25,
exponentTrend: 'up'
},
state: 0
},
],
},
};
},
methods: {
// 控制展开/收起
handleOpen() {
this.isOpen = !this.isOpen;
},
},
};
</script>
<style lang="less">
// flex样式
.flex(@justify-content,@align-items) {
display: flex;
align-items: @align-items;
justify-content: @justify-content;
}
// 边框样式
.border-style() {
background: #ffffff;
border: 1px solid #ececee;
}
.overview-system-state {
width: 100%;
padding: 20px;
.border-style();
& .add-color {
color: #ff2828;
}
& .decrease-color {
color: #33c17e;
}
&__row {
margin-bottom: 20px;
.flex(space-between, center);
}
&__labels {
border: 1px solid #e4e7ed;
& .header {
font-weight: 400;
font-size: 14px;
font-family: PingFangSC-Medium;
color: #000000 !important;
}
& .state-item {
&__span {
cursor: pointer;
}
}
.el-row {
height: 42px;
line-height: 42px;
color: #666666;
font-size: 14px;
font-weight: 400;
&:first-child {
font-family: 400;
}
&:last-child {
border-right: none;
}
}
.el-col {
height: 42px;
line-height: 42px;
border-bottom: 1px solid #e4e7ed;
border-right: 1px solid #e4e7ed;
align-items: center;
text-align: center;
&:last-child {
border-right: none;
}
}
& .status-item {
&__top {
position: relative;
&__title {
font-family: PingFangSC-Medium;
font-size: 16px;
color: #333333;
font-weight: 500;
cursor: pointer;
}
&__icon-gaowei {
color: #f55959;
}
&__icon-zhongwei {
color: #f9ad33;
}
&__icon-diwei {
color: #e1ce38;
}
&__wei {
cursor: pointer;
& span {
margin-left: 5px;
color: #606266;
}
}
}
&__status {
font-family: PingFangSC-Regular;
font-size: 14px;
color: #606266;
font-weight: 400;
&__normal {
background: #95ce68;
}
&__abnormal {
background: #f55959;
}
& span {
display: inline-block;
width: 38px;
height: 17px;
line-height: 17px;
text-align: center;
border-radius: 8px;
font-family: PingFangSC-Medium;
font-size: 12px;
color: #ffffff;
font-weight: 500;
cursor: pointer;
}
}
&__label {
margin-top: 23px;
height: 109px;
background: #f8f9fd;
padding: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
span {
font-size: 16px;
&:hover {
color: #47a5e7;
cursor: pointer;
}
}
}
}
}
&__footer {
margin-top: 10px;
text-align: center;
align-items: center;
&__item {
width: 50px;
margin: 0 auto;
}
}
}
</style>