vue实现导入json解析成动态el-table树表格
Lemon今天学习了吗 人气:0一、需求描述
前段时间接到一个需求是做一个类似接口文档的显示功能,将一段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数据的展示、修改和新增删除都已经完成,可能有些错误,欢迎大家指正~
加载全部内容