1. 需求描述:
点击添加行,增加一级目录结构 当类型为object or array
时,点击右侧➕,增加子集 点击右侧🚮,删除对应子集
2. 效果图:
3. 代码
3.1 封装组件代码
< template>
< template v-if = " !!currentLevelData.length" >
< div class = " mt10" v-for = " (item, index) in currentLevelData" :key = " `${deep}-${index}`" >
< div class = " flex flex-align-center" >
< div class = " common mr10 border-box" :style = " { paddingLeft: (deep - 1) * 10 + 'px' }" >
< a-input v-model: value= " item.key" placeholder = " 请输入key" />
</ div>
< div class = " type mr10" >
< a-select
ref = " select"
v-model: value= " item.type"
class = " full-width"
@change = " handleChange($event, item)"
>
< a-select-option v-for = " t in dataType" :value = " t" :key = " t" > {{ t }}</ a-select-option>
</ a-select>
</ div>
< div class = " common mr10" >
< a-textarea
:rows = " 1"
placeholder = " 请输入参考值"
v-model: value= " item.value"
:disabled = " objectFile.includes(item.type)"
/>
</ div>
< div class = " common mr10" >
< a-textarea :rows = " 1" placeholder = " 请输入备注" v-model: value= " item.desc" />
</ div>
< div class = " flex" >
< delete-outlined class = " ml5" @click = " deleteTarget(index)" />
< plus-outlined
class = " ml5"
v-show = " objectFile.includes(item.type)"
@click = " addSubset(item)"
/>
</ div>
</ div>
< template v-if = " !!item.child?.length" >
< CustomInputGroup :deep = " deep + 1" :list = " item.child" />
</ template>
</ div>
</ template>
</ template>
< script lang = " ts" setup >
import CustomInputGroup from './index.vue' ;
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue' ;
import { message } from 'ant-design-vue' ;
const dataType = [ 'string' , 'number' , 'boolean' , 'object' , 'array' , 'file' ] ;
const props = defineProps ( {
list : {
type : Array,
default : ( ) => [ ] ,
} ,
deep : {
type : Number,
default : 1 ,
} ,
} ) ;
const objectFile = [ 'object' , 'array' ] ;
interface paramsItem {
key : string;
type : string;
value : string;
desc : string;
child? : any;
}
const currentLevelData : any = computed ( ( ) => {
return props. list;
} ) ;
function handleChange ( type : string, item : any) {
if ( objectFile. includes ( type) ) {
item. value = '' ;
item. child = [ ] ;
} else {
delete item. child;
}
}
function addSubset ( item : any) {
const lastDeep = props. deep;
if ( lastDeep == 5 ) return message. info ( '最多支持5层结构' , 2 ) ;
item. value = '' ;
item. value = '' ;
item. child. push ( {
key : ` params ${ props. deep + 1 } - ${ item. child. length + 1 } ` ,
type : 'string' ,
value : '' ,
desc : '' ,
} ) ;
}
function deleteTarget ( index : number) {
currentLevelData. value. splice ( index, 1 ) ;
}
function getChildParams ( ) {
return currentLevelData. value;
}
defineExpose ( {
addSubset,
getChildParams,
} ) ;
</ script>
< style lang = " less" scoped >
.common {
width : 135px;
}
.type {
width : 100px !important ;
}
</ style>
3.2 父组件使用
< template>
< CustomInputGroup ref = " paramRef" :list = " formState.param" :deep = " 1" />
< a-button class = " mt10" type = " primary" @click = " addLineParam('param')" > 添加行 </ a-button>
</ template>
< script>
const formState = ( {
param : [ ]
} )
function addLineParam ( formStateKey : string) {
formState[ formStateKey] . push ( {
key : ` params ${ formState[ formStateKey] . length + 1 } ` ,
type : 'string' ,
value : '' ,
desc : '' ,
} ) ;
}
</ script>