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-selectref = " 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-outlinedclass = " 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>