Vue 复杂json数据在el-table表格中展示(el-table分割数据)

文章目录

  • 前言
  • 问题背景
  • 实现复杂json数据在el-table表格展示
    • el-table-column分割线
    • el-table-column高度


前言

在做复杂的动态表单,实现业务动态变动,比如有一条需要动态添加的el-form-item中包含了多个输入框,并实现表单验证,但在element-ui组件库中给出的表单校验中没有这样的格式,解决方法可参考文章:Element-UI 实现动态增加多个输入框并校验。

如果不想要固定格式的动态增加表单,且增加表单的类型不同,比如按钮开关、文本输入框、数字输入框,想要自由增加不同类型的表单并验证,可以参考文章:Element-UI 实现动态增加多个不同类型的输入框并校验(双重v-for表单验证)。

如果还想要还要复制多套表单且可编辑,可以参考文章:Vue 双重v-for渲染表单,再复制表单编辑之深拷贝。

表单由输入框、选择器、单选框、多选框等控件组成,动态增加各种编辑框存储格式为json,复制生成另外一套表单存储格式同样为json,不同的是,一条数据包含多个表单,而一个表单包含多个编辑框。

那么一条数据的多套表单在el-table表格该怎么做展示?下文将做讲解。


问题背景

一条复杂的json数据在el-table表格该怎么做展示?

这里有一条数据,json数据最外层有4个数组,也就说一个el-table-column要分割成4个数据,json数据如下:

[
  [
    {
      "key": "screen",
      "val": true,
      "name": "场景开关",
      "sceneType": 1
    },
    {
      "key": "showInterval",
      "val": 0,
      "name": "展示间隔(秒)",
      "sceneType": 2
    },
    {
      "key": "logicManage",
      "val": {
        "id": 5,
        "content": [
          {
            "key": "N",
            "val": "6",
            "name": "N"
          }
        ]
      },
      "name": "逻辑管理",
      "sceneType": 3
    },
    {
      "key": "controlManage",
      "val": [
        {
          "id": 6,
          "content": [
            {
              "key": "showRegions",
              "val": "|214|215|994|995|2163|",
              "name": "展示地区",
              "type": 9
            },
            {
              "key": "showTimeRange",
              "val": [
                [
                  "04:59",
                  "10:59"
                ],
                [
                  "05:13",
                  "20:25"
                ],
                [
                  "00:00",
                  "07:00"
                ]
              ],
              "name": "展示时段",
              "type": 10
            }
          ]
        }
      ],
      "name": "控制管理",
      "sceneType": 4
    },
    {
      "key": "select",
      "val": [
        {
          "id": 1,
          "dayLimits": 0,
          "showProbability": 100,
          "errorProbability": 100
        },
        {
          "id": 2,
          "dayLimits": 0,
          "showProbability": 100,
          "errorProbability": 100
        }
      ],
      "name": "选择",
      "sceneType": 5
    }
  ],
  [
    {
      "key": "screen",
      "val": false,
      "name": "场景开关",
      "sceneType": 1
    },
    {
      "key": "showInterval",
      "val": 0,
      "name": "展示间隔(秒)",
      "sceneType": 2
    },
    {
      "key": "logicManage",
      "val": {
        "id": 5,
        "content": [
          {
            "key": "N",
            "val": "6",
            "name": "N"
          }
        ]
      },
      "name": "逻辑管理",
      "sceneType": 3
    },
    {
      "key": "controlManage",
      "val": [
        {
          "id": 8,
          "content": [
            {
              "key": "isNetwork",
              "val": true,
              "name": "联网",
              "type": 11
            }
          ]
        },
        {
          "id": 1,
          "content": [
            {
              "key": "isFullScreenTrigger",
              "val": true,
              "name": "全屏触发",
              "type": 1
            },
            {
              "key": "triggerRate",
              "val": 30,
              "name": "触发概率(%)",
              "type": 2
            }
          ]
        },
        {
          "id": 4,
          "content": [
            {
              "key": "exchangeRate",
              "val": 30,
              "name": "互换概率(%)",
              "type": 7
            }
          ]
        },
        {
          "id": 5,
          "content": [
            {
              "key": "isFalsePause",
              "val": true,
              "name": "假暂停",
              "type": 8
            }
          ]
        },
        {
          "id": 2,
          "content": [
            {
              "key": "triggerRate",
              "val": 30,
              "name": "触发概率(%)",
              "type": 2
            }
          ]
        }
      ],
      "name": "控制管理",
      "sceneType": 4
    },
    {
      "key": "select",
      "val": [
        {
          "id": 2,
          "dayLimits": 0,
          "showProbability": 100,
          "errorProbability": 100
        },
        {
          "id": 1,
          "dayLimits": 0,
          "showProbability": 100,
          "errorProbability": 100
        },
        {
          "id": 9,
          "dayLimits": 1,
          "showProbability": 100,
          "errorProbability": 100
        }
      ],
      "name": "选择",
      "sceneType": 5
    }
  ],
  [
    {
      "key": "screen",
      "val": true,
      "name": "场景开关",
      "sceneType": 1
    },
    {
      "key": "showInterval",
      "val": 1,
      "name": "展示间隔(秒)",
      "sceneType": 2
    },
    {
      "key": "logicManage",
      "val": {
        "id": 5,
        "content": [
          {
            "key": "N",
            "val": "6",
            "name": "N"
          }
        ]
      },
      "name": "逻辑管理",
      "sceneType": 3
    },
    {
      "key": "controlManage",
      "val": [
        {
          "id": 8,
          "content": [
            {
              "key": "isNetwork",
              "val": true,
              "name": "联网",
              "type": 11
            }
          ]
        }
      ],
      "name": "控制管理",
      "sceneType": 4
    },
    {
      "key": "select",
      "val": [
        {
          "id": 1,
          "dayLimits": 2,
          "showProbability": 100,
          "errorProbability": 100
        }
      ],
      "name": "选择",
      "sceneType": 5
    }
  ],
  [
    {
      "key": "screen",
      "val": false,
      "name": "场景开关",
      "sceneType": 1
    },
    {
      "key": "showInterval",
      "val": 1,
      "name": "展示间隔(秒)",
      "sceneType": 2
    },
    {
      "key": "logicManage",
      "val": {
        "id": 2,
        "content": [
          {
            "key": "N",
            "val": "3",
            "name": "N"
          },
          {
            "key": "interval",
            "val": "5",
            "name": "间隔(秒)"
          }
        ]
      },
      "name": "逻辑管理",
      "sceneType": 3
    },
    {
      "key": "controlManage",
      "val": [
        {
          "id": 5,
          "content": [
            {
              "key": "isFalsePause",
              "val": true,
              "name": "假暂停",
              "type": 8
            }
          ]
        }
      ],
      "name": "控制管理",
      "sceneType": 4
    },
    {
      "key": "select",
      "val": [
        {
          "id": 2,
          "dayLimits": 2,
          "showProbability": 100,
          "errorProbability": 100
        },
        {
          "id": 1,
          "dayLimits": 0,
          "showProbability": 100,
          "errorProbability": 100
        }
      ],
      "name": "选择",
      "sceneType": 5
    }
  ]
]

可以看到,最外层的数据都包含 sceneType ,这个key使用来得知内部数据结构,解析的时候得到sceneType的类型就可以直接解析它内部。

key 是用于数据下发时用到的键,如不需要下发,只是在界面做编辑和展示,可省略。

实现复杂json数据在el-table表格展示

先看实现效果图:

Vue 复杂json数据在el-table表格中展示(el-table分割数据)_第1张图片

部分代码如下:

  • 场景开关根据权限来决定是否显示el-switch开关,无权限直接显示文字
  • 多个控制逻辑不做分割,分行显示
<el-table-column label="场景开关" align="center" prop="content">
  <template slot-scope="scope">
    <template>
      <div v-for="(item, index) in scope.row.content" :key="index" class="flex-box self-cell" :style="checkHight(item)">
        <span v-for="(arr, arrIndex) in item" :key="arrIndex">
          <span v-if="arr.sceneType === 1">
            <el-switch v-if="checkPermission(['admin','scene:edit'])" v-model="arr.val" active-color="#409EFF" inactive-color="#F56C6C" @change="changeEnabled(scope.row, arr.val, index, arrIndex)" />
            <span v-else>{{ arr.val ? '开' : '关' }}span>
          span>
        span>
      div>
    template>
  template>
el-table-column>

<el-table-column label="控制逻辑" align="center" prop="content">
  <template slot-scope="scope">
    <span v-for="(item, index) in scope.row.content" :key="index" class="flex-box self-cell" :style="checkHight(item)">
      <span v-for="(arr, arrIndex) in item" :key="arrIndex">
        <span v-if="arr.sceneType === 4">
          <span v-for="(controlItem, controlIndex) in arr.val" :key="controlIndex">
            <span v-if="controlIndex !== 0"><br>span>
            <span>{{ getName(controlManage, controlItem.id) }}span>
          span>
        span>
      span>
    span>
  template>
el-table-column>

<el-table-column v-if="columns.visible('content')" label="选择" align="center" prop="content">
  <template slot-scope="scope">
    <div v-for="(item, index) in scope.row.content" :key="index" class="flex-box self-cell" :style="checkHight(item)">
      <span v-for="(arr, arrIndex) in item" :key="arrIndex">
        <span v-if="arr.sceneType === 5">
          <span v-for="(selectItem, selectIndex) in arr.val" :key="selectIndex" class="flex-box-2 self-cell">
            <span>{{ getName(selects, selectItem.id) }}span>
          span>
        span>
      span>
    div>
  template>
el-table-column>

el-table-column分割线

上面的代码可以看到

  • 第一层v-for写入了 class="flex-box self-cell",用于显示分割线
  • 需要再分割的v-for写入了 class="flex-box2 self-cell",用于显示分割线

如需要动态决定所需分割的列,可用函数动态修改 flex-box,此处不做讲解,只是复制了flex-box命名为flex-box2,并添加属性 min-width: 9999px;,用于显示第二层分割线的长度。

css如下:

  .flex-box {
    align-items: center;
    display: flex;
    height: 60px;
    justify-content: center;
    padding: 0 6px;
  }
  
  .flex-box-2 {
    align-items: center;
    display: flex;
    height: 60px;
    min-width: 9999px;
    justify-content: center;
    padding: 0 6px;
  }

  /deep/ .el-table .el-table__cell.table__cell {
    padding: 0;
  }

  /deep/ .el-table .cell {
    padding: 0 !important;
  }

  /deep/ .el-table .cell .self-cell {
    border-bottom: 1px solid #d3d5d9;
    padding: 6px 5px;
  }

  /deep/ .el-table .cell .self-cell:last-child {
    border-bottom: none;
  }
  

el-table-column高度

第一层v-for还包含 :style="checkHight(item)",用于检测当前行所需要的高度。

从上面的css代码得知,每一行的固定高度为60px,那么,如果分割中的行数再进行分割呢?

分割一次,一条数据的高度应该为120px,如果再分割一次,一条数据的高度为180px,那么就需要写函数来控制。

至于高度应该是多少,还取决于其它列的最高高度。

为什么?先看上面这句话 多个控制逻辑不做分割,分行显示,也就就说控制逻辑高度是不固定的,有多个就换行显示,那么高度动态增加的,不能还是设置60px,效果如图:

Vue 复杂json数据在el-table表格中展示(el-table分割数据)_第2张图片

可以看到,第二个分割行的高度不止60px,checkHight()函数实现如下:

checkHight(item) {
  let num1 = 60
  let num2 = 60
  for (var i = 0; i < item.length; i++) {
    if (item[i].sceneType === 4) {
      num1 = item[i].val.length * 30
    }
    if (item[i].sceneType === 5) {
      num2 = item[i].val.length * 60
    }
  }
  return [{
    height: Math.max(num1, num2) + 'px'
  }]
}

你可能感兴趣的:(Vue,vue.js,json,javascript)