vue實(shí)現(xiàn)導(dǎo)入json解析成動(dòng)態(tài)el-table樹(shù)表格
一、需求描述
前段時(shí)間接到一個(gè)需求是做一個(gè)類(lèi)似接口文檔的顯示功能,將一段json數(shù)據(jù)貼到里面就可以自動(dòng)解析出json數(shù)據(jù)的每個(gè)字段的類(lèi)型和層級(jí)關(guān)系,用element組件的樹(shù)表格的形式展示,并且可以手動(dòng)新增、修改和刪除某個(gè)數(shù)據(jù)字段。
二、界面展示
功能如下圖所示:
1.未貼數(shù)據(jù)之前:
2.點(diǎn)擊右上角的‘導(dǎo)入json',在打開(kāi)的彈框中貼入如下json數(shù)據(jù):{"name":"lemon","sex":"女","age":18,"hobby":{"hobby1":"敲代碼","hobby2":"跳恰恰"},"likeArr":["水果","青菜"]}
3.點(diǎn)擊確認(rèn)后樹(shù)表格自動(dòng)展示貼入的json數(shù)據(jù),如下圖所示;
4.點(diǎn)擊每行的最右側(cè)可以進(jìn)行新增和刪除操作;
5.點(diǎn)擊tab切換到預(yù)覽展示效果:
三、代碼實(shí)現(xiàn)
彈框代碼展示,新建一個(gè)jsonDialog.vue文件,MonacoEditor是一個(gè)json編輯器,實(shí)現(xiàn)以下代碼:
<template> <el-dialog title="導(dǎo)入 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()">確認(rèn)</el-button> </span> </el-dialog> </template> <script> export default { components: { MonacoEditor: () => import('@/components/MonacoEditor') }, data() { return { dialogFormVisible: false, jsonData: null, //返回參數(shù) } }, methods: { open() { this.dialogFormVisible = true }, close() { this.dialogFormVisible = false this.jsonData = '' }, // 提交 onSubmit() { if (!this.jsonData) return this.$message.error('json數(shù)據(jù)不能為空') let flag = this.checkJson(data) if (flag) { this.dialogFormVisible = false this.$emit('getJson', data) } else { return this.$message.error('json數(shù)據(jù)格式不正確') } }, // 判斷是否是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>
界面代碼展示,新建一個(gè)jsonIndex.vue界面,實(shí)現(xiàn)以下代碼:
<!-- 返回?cái)?shù)據(jù)設(shè)置 --> <div class="panel-item"> <div class="panel-item-title">返回參數(shù)</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')"> 導(dǎo)入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="參數(shù)名稱"> <template slot-scope="scopes"> <el-input placeholder="name" v-model="scopes.row.jsonName"> </el-input> </template> </el-table-column> <el-table-column label="參數(shù)類(lèi)型"> <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="刪除節(jié)點(diǎn)" 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="添加子節(jié)點(diǎn)" 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="預(yù)覽" 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>
展示界面的功能代碼,對(duì)導(dǎo)入json的展示及相關(guān)操作的實(shí)現(xiàn):
<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 }, // 導(dǎo)入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導(dǎo)入數(shù)據(jù) 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導(dǎo)入數(shù)據(jù)轉(zhuǎn)換 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 }, // 判斷數(shù)據(jù)類(lèi)型 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 = '未進(jìn)行判斷的類(lèi)型:' + type } return type }, // 新增json數(shù)據(jù) addJsonClick(type) { if(type=='resp'){ // if(this.threeStepData.responseParams?.length==1){ // this.$message.closeAll(); // this.$message.error('請(qǐng)勿重復(fù)添加根節(jié)點(diǎn)!'); // return; // } let obj = { id: this.guid(), jsonName: '', jsonType: 'object', jsonRemark: '', // pid: 0, children: [] } this.threeStepData.responseParams.push(obj) } }, //添加子節(jié)點(diǎn) 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數(shù)據(jù) 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>
綜上所述,已經(jīng)完成了json數(shù)據(jù)的展示、修改和新增刪除都已經(jīng)完成,可能有些錯(cuò)誤,歡迎大家指正~
到此這篇關(guān)于vue實(shí)現(xiàn)導(dǎo)入json解析成動(dòng)態(tài)el-table樹(shù)表格的文章就介紹到這了,更多相關(guān)vue json解析成動(dòng)態(tài)el-table樹(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue點(diǎn)擊按鈕跳轉(zhuǎn)到另一個(gè)vue頁(yè)面實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于vue點(diǎn)擊按鈕跳轉(zhuǎn)到另一個(gè)vue頁(yè)面的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08在VUE中使用lodash的debounce和throttle操作
這篇文章主要介紹了在VUE中使用lodash的debounce和throttle操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11vue中img src 動(dòng)態(tài)加載本地json的圖片路徑寫(xiě)法
這篇文章主要介紹了vue中的img src 動(dòng)態(tài)加載本地json的圖片路徑寫(xiě)法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04基于Vue+elementUI實(shí)現(xiàn)動(dòng)態(tài)表單的校驗(yàn)功能(根據(jù)條件動(dòng)態(tài)切換校驗(yàn)格式)
這篇文章主要介紹了Vue+elementUI的動(dòng)態(tài)表單的校驗(yàn)(根據(jù)條件動(dòng)態(tài)切換校驗(yàn)格式),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04vue-router+vuex addRoutes實(shí)現(xiàn)路由動(dòng)態(tài)加載及菜單動(dòng)態(tài)加載
本篇文章主要介紹了vue-router+vuex addRoutes實(shí)現(xiàn)路由動(dòng)態(tài)加載及菜單動(dòng)態(tài)加載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09vue?background-image?不顯示問(wèn)題的解決
這篇文章主要介紹了vue?background-image?不顯示問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue init webpack 項(xiàng)目初始化失敗問(wèn)題
在使用Vue-cli搭建項(xiàng)目時(shí),可能會(huì)遇到依賴無(wú)法顯示版本號(hào)的問(wèn)題,首先檢查環(huán)境變量配置是否正確,確保vue-init的安裝目錄被正確添加到path中,若問(wèn)題仍未解決,嘗試卸載并重新安裝webpack,確保在正確的項(xiàng)目路徑下執(zhí)行npm install和npm run dev命令2024-09-09vue實(shí)現(xiàn)大轉(zhuǎn)盤(pán)抽獎(jiǎng)功能
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)大轉(zhuǎn)盤(pán)抽獎(jiǎng)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03Vue實(shí)現(xiàn)子組件向父組件傳遞多個(gè)參數(shù)的方法
在Vue框架中,組件間的通信是一個(gè)常見(jiàn)的需求,特別是在子組件需要向父組件傳遞多個(gè)參數(shù)時(shí),合理的通信方式可以顯著提升代碼的可讀性和可維護(hù)性,本文將詳細(xì)介紹如何在Vue中實(shí)現(xiàn)子組件向父組件傳遞多個(gè)參數(shù),需要的朋友可以參考下2024-10-10