需求是:通过手动add生成json数据,包括树形结构数据,value的类型有三种可以选择,String、Number、Object。有可以改进的地方还希望大家不吝赐教
DOM结构递归
<a-tabs v-if="paramsType === 1" @change="tabCallback">
<a-tab-pane key="1" tab="模板">
<div class="params-model" v-if="currentTab === '1'">
<ul class="params-list">
<li class="params-item">
<div class="input-wrap">
<span>key</span>
<span>value类型</span>
<span>value</span>
</div>
<div class="tools-wrap">
<span>增加</span>
<span>删除</span>
</div>
</li>
<li v-for="item in paramsList" :key="item.id">
<div class="params-item">
<div class="input-wrap">
<span><a-input v-model="item.key" placeholder="请输入key"></a-input></span><!--key-->
<span>
<a-select v-model="item.type" style="width: 192px" default-value="String">
<a-select-option value="String">
String
</a-select-option>
<a-select-option value="Number">
Number
</a-select-option>
<a-select-option value="Object">
Object
</a-select-option>
</a-select>
</span><!--value type-->
<span><a-input :disabled="item.type === 'Object'" v-model="item.value" placeholder="请输入value"></a-input></span><!--value-->
</div>
<div class="tools-wrap">
<span class="add-wrap blue">
<a-icon class="add-item" @click="addJsonBtn(item)" type="plus" />
<div v-if="item.type === 'Object'" class="add-type-wrap">
<p @click="addObjectBtn(item, '1')" class="item">兄弟节点</p>
<p @click="addObjectBtn(item, '2')" class="item">子节点</p>
</div>
</span>
<span v-if="item.id !== 0" @click="deleteBtn(item)" class="red"><a-icon type="close" /></span>
</div>
</div>
<ul class="params-list" v-if="item.children && item.children.length">
<dialog-params-node :paramsList="item.children"></dialog-params-node>
</ul>
</li>
</ul>
</div>
</a-tab-pane>
<a-tab-pane key="2" tab="预览">
<div>
<textarea v-if="currentTab === '2'" rows="5" cols="100" v-html="previewObj" />
<p v-else>暂无数据</p>
</div>
</a-tab-pane>
</a-tabs>
子组件
<li v-for="item in paramsList" :key="item.id">
<div class="params-item">
<div class="input-wrap">
<span :style="'padding-left:' + item.style * 10 + 'px'" ><a-input v-model="item.key" placeholder="请输入key"></a-input></span><!--key-->
<span>
<a-select v-model="item.type" style="width: 192px" default-value="String">
<a-select-option value="String">
String
</a-select-option>
<a-select-option value="Number">
Number
</a-select-option>
<a-select-option value="Object">
Object
</a-select-option>
</a-select>
</span><!--value type-->
<span><a-input :disabled="item.type === 'Object'" v-model="item.value" placeholder="请输入value"></a-input></span><!--value-->
</div>
<div class="tools-wrap">
<span class="add-wrap blue">
<a-icon class="add-item" @click="addJsonBtn(item)" type="plus" />
<div v-if="item.type === 'Object'" class="add-type-wrap">
<p @click="addObjectBtn(item, '1')" class="item">兄弟节点</p>
<p @click="addObjectBtn(item, '2')" class="item">子节点</p>
</div>
</span>
<span v-if="item.id !== 0" @click="deleteBtn(item)" class="red"><a-icon type="close" /></span>
</div>
</div>
<ul class="params-list" v-if="item.children && item.children.length">
<dialog-params :paramsList="item.children"></dialog-params>
</ul>
</li>
js
methods: {
paramsDataOk () {
if (this.paramsType === 1) {
// 手动输入
this.previewJson()
this.$emit('paramsOk', this.previewObj)
} else {
// 导入json
this.$emit('paramsOk', JSON.parse(this.paramsText))
}
this.$emit('update:showParams', false)
},
tabCallback (key) {
if (key === '2') {
this.previewJson()
}
this.currentTab = key
},
previewJson () {
// 预览
const json = {}
this.paramsList.forEach(item => {
if (item.type === 'Number') {
json[item.key] = Number(item.value)
} else if (item.type === 'Object') {
json[item.key] = {}
if (item.hasOwnProperty('children')) {
item.children.forEach(element => {
if (element.type === 'Number') {
json[item.key][element.key] = Number(element.value)
} else if (element.type === 'Object') {
json[item.key][element.key] = {}
} else {
json[item.key][element.key] = element.value
}
// json[item.key][element.key] = element.value
if (element.hasOwnProperty('children')) {
this.parsingJson(json[item.key][element.key], element.children)
}
})
}
} else {
json[item.key] = item.value
}
})
this.previewObj = json
},
parsingJson (json, array) {
for (let index = 0; index < array.length; index++) {
const element = array[index]
if (element.type === 'Number') {
json[element.key] = Number(element.value)
} else if (element.type === 'Object') {
json[element.key] = {}
} else {
json[element.key] = element.value
}
if (element.hasOwnProperty('children') === false) {
if (element.type === 'Number') {
json[element.key] = Number(element.value)
} else if (element.type === 'Object') {
json[element.key] = {}
} else {
json[element.key] = element.value
}
break
} else {
this.parsingJson(json[element.key], element.children)
}
}
},
addJsonBtn (row) {
if (row.type !== 'Object') {
this.addItem(row)
}
},
addItem (row) {
const obj = { id: this.getID(3), value: '', key: '', type: 'String', style: 1 }
this.paramsList.forEach((item, index) => {
if (item.id === row.id) {
this.paramsList.splice(index + 1, 0, obj)
}
})
},
addObjectBtn (row, type) {
// type 1-兄弟节点 2-子节点
switch (type) {
case '1':
this.addItem(row)
break
case '2': {
const obj = { id: this.getID(3), parentId: row.id, value: '', key: '', type: 'String', style: row.style + 1 }
const arr = JSON.parse(JSON.stringify(this.paramsList))
arr.forEach((item, index) => {
if (item.id === row.id) {
if (item.hasOwnProperty('children') === false) {
item.children = []
}
item.children.push(obj)
// this.paramsList.splice(index + 1, 0, obj)
}
})
this.paramsList = arr
}
break
}
},
deleteBtn (row) {
this.paramsList.forEach((item, index) => {
if (item.id === row.id) {
this.paramsList.splice(index, 1)
}
})
},
cancelBtn () {
this.$emit('update:showParams', false)
},
getID (length) {
return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36)
}
},