vue实现导入json解析成动态el-table树表格

一、需求描述

前段时间接到一个需求是做一个类似接口文档的显示功能,将一段json数据贴到里面就可以自动解析出json数据的每个字段的类型和层级关系,用element组件的树表格的形式展示,并且可以手动新增、修改和删除某个数据字段。

二、界面展示

功能如下图所示:

1.未贴数据之前:

2.点击右上角的‘导入json',在打开的弹框中贴入如下json数据:{"name":"lemon","sex":"女","age":18,"hobby":{"hobby1":"敲代码","hobby2":"跳恰恰"},"likeArr":["水果","青菜"]}

3.点击确认后树表格自动展示贴入的json数据,如下图所示;

4.点击每行的最右侧可以进行新增和删除操作;

5.点击tab切换到预览展示效果:

三、代码实现

弹框代码展示,新建一个jsonDialog.vue文件,MonacoEditor是一个json编辑器,实现以下代码:

<template>
 <el-dialog
 title="导入 json"
 :visible.sync="dialogFormVisible"
 :close-on-click-modal="false"
 :modal-append-to-body="false"
 width="35%"
 @close="close"
 class="my_dialog"
 >
 <div class="empi_dialog_form">
 <!-- 返回 -->
 <div v-if="type == 'resp'">
 <monaco-editor v-model="jsonData" language="json" :readOnly="false"></monaco-editor>
 </div>
 </div>
 <span slot="footer" class="dialog-footer">
 <el-button @click="close">取 消</el-button>
 <el-button type="primary" @click="onSubmit()">确认</el-button>
 </span>
 </el-dialog>
</template>
<script>
export default {
 components: {
 MonacoEditor: () => import('@/components/MonacoEditor')
 },
 data() {
 return {
 dialogFormVisible: false,
 jsonData: null, //返回参数
 }
 },
 methods: {
 open() {
 this.dialogFormVisible = true
 },
 close() {
 this.dialogFormVisible = false
 this.jsonData = ''
 },
 // 提交
 onSubmit() {
 if (!this.jsonData) return this.$message.error('json数据不能为空')
 let flag = this.checkJson(data)
 if (flag) {
 this.dialogFormVisible = false
 this.$emit('getJson', data)
 } else {
 return this.$message.error('json数据格式不正确')
 }
 },
 // 判断是否是json格式
 checkJson(str) {
 if (typeof str == 'string') {
 try {
 let obj = JSON.parse(str)
 if (typeof obj == 'object' && obj) {
 return true
 } else {
 return false
 }
 } catch (e) {
 //console.log('error:' + str + '!!!' + e)
 return false
 }
 }
 //console.log('It is not a string!')
 }
 }
}
</script>

界面代码展示,新建一个jsonIndex.vue界面,实现以下代码:

<!-- 返回数据设置 -->
<div class="panel-item">
 <div class="panel-item-title">返回参数</div>
 <el-radio-group v-model="checkRespLabel"
 size="mini" class="radio_btn_group">
 <el-radio-button label="JSON">
 </el-radio-button>
 </el-radio-group>
 <div class="panel-item-tab">
 <div class="blue json-btn" v-show="activeTabName == 'first'" @click="addJsonClick('resp')" > 添加 </div>
 <div class="blue json-btn" v-show="activeTabName == 'first'" @click="toJsonClick('resp')"> 导入json </div>
 <el-tabs v-model="activeTabName" type="card" class="card-tab">
 <el-tab-pane label="模板" name="first">
 <el-table
 :data="threeStepData.responseParams"
 class="json-table"
 :show-header="false"
 :highlight-current-row="false"
 row-key="id" size="medium"
 default-expand-all
 :tree-props="{children: 'children',hasChildren: 'hasChildren'}">
 <el-table-column label="参数名称">
 <template slot-scope="scopes">
 <el-input placeholder="name" v-model="scopes.row.jsonName">
 </el-input>
 </template>
 </el-table-column>
 <el-table-column label="参数类型">
 <template slot-scope="scopes">
 <el-select v-model="scopes.row.jsonType" placeholder="type">
 <el-option
 v-for="item in typeData"
 :key="item.value"
 :label="item.label"
 :value="item.value">
 </el-option>
 </el-select>
 </template>
 </el-table-column>
 <el-table-column label="备注">
 <template slot-scope="scopes">
 <el-input placeholder="备注" v-model="scopes.row.jsonRemark">
 </el-input>
 </template>
 </el-table-column>
 <el-table-column label="操作" width="150">
 <template slot-scope="scopes">
 <el-tooltip
 class="item"
 effect="dark"
 content="删除节点"
 placement="top" :open-delay="500">
 <i class="blue el-icon-close" @click="removeJsonClick(scopes.row, 'resp')"></i>
 </el-tooltip>
 <el-tooltip
 class="item"
 effect="dark"
 content="添加子节点"
 placement="top" :open-delay="500">
 <i class="blue el-icon-plus" @click="addJsonChildrenClick(scopes.row, 'resp')"></i>
 </el-tooltip>
 </template>
 </el-table-column>
 </el-table>
 </el-tab-pane>
 <el-tab-pane label="预览" name="second">
 <div class="panel-item-content">
 <el-input type="textarea" disabled :rows="5" v-model="strParams">
 </el-input>
 </div>
 </el-tab-pane>
 </el-tabs>
 </div>
 </div>
//弹框
<jsonDialog ref="jsonDialog" @getJson="getJson"></jsonDialog>

展示界面的功能代码,对导入json的展示及相关操作的实现:

<script>
export default {
 components: {
 MonacoEditor: () => import('@/components/MonacoEditor'),
 jsonDialog: () => import('./../dialog/jsonDialog')
 },
 data() {
 return {
 threeStepData: {
 responseParams: [
 // {
 // id: 1,
 // jsonName: 'root',
 // jsonType: 'object',
 // jsonRemark: '备注',
 // pid: 0,
 // children: []
 // }
 ]
 },
 checkRespLabel: 'JSON',
 activeTabName: 'first',
 typeData: [
 { label: 'string', value: 'string' },
 { label: 'number', value: 'number' },
 { label: 'array', value: 'array' },
 { label: 'object', value: 'object' },
 { label: 'boolean', value: 'boolean' }
 ]
 }
 },
 computed: {
 strParams() {
 return this.threeStepData?.responseParams
 ? JSON.stringify(this.threeStepData.responseParams)
 : '-'
 },
 },
 methods: {
 open(data) {
 this.threeStepData = data
 },
 // 导入json
 toJsonClick(type) {
 this.$refs.jsonDialog.open(type)
 },
 // 生成唯一id
 guid() {
 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
 /[xy]/g,
 function (c) {
 let r = (Math.random() * 16) | 0,
 v = c == 'x' ? r : (r & 0x3) | 0x8
 return v.toString(16)
 }
 )
 },
 // 获取json导入数据
 getJson(data, type) {
 let _data = JSON.parse(data)
 let _type = this.getJsonType(_data)
 let arr = []
 if (_type === 'object') {
 arr = this.handleJson(_data)
 }
 if (type == 'resq') {
 this.threeStepData.responseParams = arr
 // this.threeStepData.responseParams[0].children = arr
 }
 },
 // json导入数据转换
 handleJson(data) {
 let arr = []
 Object.keys(data).map((key) => {
 let _type = this.getJsonType(data[key])
 if (_type && _type == 'object') {
 let children = this.handleJson(data[key])
 arr.push({
 id: this.guid(),
 pid: data.id,
 jsonName: key,
 jsonType: _type,
 jsonRemark: '',
 children
 })
 } else {
 arr.push({
 id: this.guid(),
 jsonName: key,
 jsonType: _type,
 jsonRemark: ''
 })
 }
 })
 return arr
 },
 // 判断数据类型
 getJsonType(data) {
 let type = Object.prototype.toString.call(data)
 if (type === '[object String]') {
 type = 'string'
 } else if (type === '[object Number]') {
 type = 'number'
 } else if (type === '[object Null]') {
 type = 'null'
 } else if (type === '[object Boolean]') {
 type = 'boolean'
 } else if (type === '[object Array]') {
 type = 'array'
 } else if (type === '[object Object]') {
 type = 'object'
 } else {
 type = '未进行判断的类型:' + type
 }
 return type
 },
 
 // 新增json数据
 addJsonClick(type) {
 if(type=='resp'){
 // if(this.threeStepData.responseParams?.length==1){
 // this.$message.closeAll();
 // this.$message.error('请勿重复添加根节点!');
 // return;
 // }
 let obj = {
 id: this.guid(),
 jsonName: '',
 jsonType: 'object',
 jsonRemark: '',
 // pid: 0,
 children: []
 }
 this.threeStepData.responseParams.push(obj)
 }
 },
 //添加子节点
 addJsonChildrenClick(data, type) {
 let obj = {
 id: this.guid(),
 jsonName: '',
 jsonType: 'string',
 jsonRemark: '',
 pid: data.id
 }
 let node = this.addNode(this.threeStepData.responseParams, data.id, obj)
 if (type === 'resp') {
 this.threeStepData.responseParams = JSON.parse(JSON.stringify(node))
 }
 },
 addNode(list, pid, obj) {
 list.forEach((e) => {
 if (e.id == pid) {
 e.children ? e.children.push(obj) : (e.children = [obj])
 } else {
 if (e.children && e.children.length > 0) {
 this.addNode(e.children, pid, obj)
 }
 }
 })
 return list
 },
 // 移除json数据
 removeJsonClick(data, type) {
 let objMap = {
 resp: this.threeStepData.responseParams,
 }
 let node = this.removeItem(objMap[type], data.id)
 if (type === 'resp') {
 this.threeStepData.responseParams = JSON.parse(JSON.stringify(node))
 }
 },
 removeItem(root, id) {
 root.forEach((e, i) => {
 if (e.id === id) {
 root.splice(i, 1)
 } else if (e.children && e.children.length > 0) {
 this.removeItem(e.children, id)
 }
 })
 return root
 }
 }
}
</script>

综上所述,已经完成了json数据的展示、修改和新增删除都已经完成,可能有些错误,欢迎大家指正~

作者:Lemon今天学习了吗原文地址:https://blog.csdn.net/weixin_47978760/article/details/128718910

%s 个评论

要回复文章请先登录注册