vue3自定義動態(tài)不同UI組件篩選框案例
?1. 實現(xiàn)功能
??添加條件進行數(shù)據(jù)篩選
- 根據(jù)篩選數(shù)據(jù)條件不同,顯示不同的UI組件:包含
datetime
、select
、input
等 - 篩選完條件可繼續(xù)添加與取消條件
- 當然可以在條件列表中進行直接刪除,當刪除完所有條件之后,回到添加條件頁面
- 清空搜索條件直接回到添加條件頁面
?2. 效果圖
??打開篩選條件彈窗??
????查看篩選條件不同的UI
結(jié)構(gòu)效果預(yù)覽????
??????繼續(xù)添加和取消篩選條件效果??????
????條件列表中直接刪除條件效果????
??清空搜索條件效果??
?3. 組件代碼
??1. 組件目錄結(jié)構(gòu)
?? 2. 添加條件頁面
<script setup lang="ts"> import { ref } from 'vue' import { NavData } from './constant' import AddedCondition from './components/added-condition/index.vue' defineOptions({ name: 'SearchClues', }) const { token } = useAntdToken() // 是否有搜索添加,判斷顯示篩選區(qū)域 const isNav = ref(true) // 添加條件彈窗 const AddedConditionRef = ref() function handleClick(i: number) { if (i === 0) { AddedConditionRef.value.handleOpen() return } if (i === 1) { console.log(1) return } if (i === 2) { console.log(2) } } // 篩選條件判斷 function handleIsPanel(v: boolean) { isNav.value = !v if (isNav.value && !v) { isSearch.value = false } } function handleSearch(list: any) { console.log(list, 'handleSearch') isSearch.value = true } // 是否搜索 const isSearch = ref<boolean>(false) </script> <template> <div> <a-card> <div v-if="isNav" class="flex"> <div v-for="(nav, i) in NavData" :key="i" class="flex-center cursor-pointer m-ie-8" @click="handleClick(nav.i)"> <div class="flex-center p-2 b-rd-10 m-ie-2" :style="{ 'background-color': token?.colorPrimary }"> <img :src="nav.url" width="24" height="24" alt=""> </div> <span>{{ nav.title }}</span> </div> </div> <AddedCondition ref="AddedConditionRef" @handle-is-panel="handleIsPanel" @handle-search="handleSearch" /> </a-card> <a-card class="m-t-5"> <div> <h2>三步完成線索查找</h2> <div>待完成</div> </div> </a-card> </div> </template> <style lang="less" scoped></style>
??3. 選擇條件-條件列表added-condition/index.vue ??
<script setup lang="ts"> import { createVNode, ref } from 'vue' import { DownOutlined, ExclamationCircleOutlined, MinusCircleOutlined, PlusOutlined, UpOutlined } from '@ant-design/icons-vue' import { Modal, message } from 'ant-design-vue' import { JudgementCondition } from '../../constant' import SelectCondition from './select-condition.vue' import type { Condition } from '@/api/interface/getting-clues' defineOptions({ name: 'AddedCondition', }) const emit = defineEmits(['handleIsPanel', 'handleSearch', 'handleSave', 'handleClear']) const selectionConditionRef = ref() function handleOpen() { selectionConditionRef.value.handleOpen() } // 是否有搜索添加,判斷顯示篩選區(qū)域 const isPanel = ref(false) function handleOk(list: Condition.ConditionItem[]) { conditionsList.value = list isPanel.value = true emit('handleIsPanel', isPanel.value) } /** * @constant searchGeneralType 搜索條件總類型 * @constant conditionsList 搜索條件列表 */ const searchGeneralType = ref('0') const conditionsList = ref<Condition.ConditionItem[]>([]) // 獲取下拉框數(shù)據(jù) function getDefaultOptions(condition: Condition.ConditionItem) { if (condition.type === 'SelectOption') { return condition.keys?.map(item => ( JudgementCondition[item.key][item.value] || JudgementCondition.renderData.ifData ))[0] } else { return JudgementCondition.type.operateState } } // 獲取多選條件下拉框數(shù)據(jù) function getKeysOptions() { return JudgementCondition.default.default } function handleDelete(index: number) { conditionsList.value.splice(index, 1) } watch(() => conditionsList, (n) => { if (n.value.length === 0) { isPanel.value = false emit('handleIsPanel', isPanel.value) } }, { deep: true }) // 篩選 function handleSearch() { emit('handleSearch', conditionsList.value) } // 保存 const loading = ref<boolean>(false) function handleSave() { Modal.confirm({ title: '確認', icon: createVNode(ExclamationCircleOutlined), content: '確定要保存此篩選條件嗎?', onOk() { loading.value = true emit('handleSave', conditionsList.value) setTimeout(() => { message.success('保存成功') loading.value = false }, 1000) }, onCancel() { console.log('Cancel') }, }) } // 清空 function handleClear() { Modal.confirm({ title: '確認', icon: createVNode(ExclamationCircleOutlined), content: '確定要清空篩選條件嗎?', onOk() { conditionsList.value = [] emit('handleClear', conditionsList.value) selectionConditionRef.value.reset() }, onCancel() { console.log('Cancel') }, }) } // 展開折疊 const isExpanded = ref<boolean>(true) function handleCollapse() { isExpanded.value = !isExpanded.value } defineExpose({ handleOpen, handleSearch, handleSave, handleClear, }) </script> <template> <div> <div v-if="isPanel"> <div class="m-be-5"> <span class="w-16 inline-block">滿足下列</span> <a-select v-model:value="searchGeneralType" class="m-inline-2.5" style="width: 120px"> <a-select-option value="0"> 所有 </a-select-option> <a-select-option value="1"> 任一 </a-select-option> </a-select> 條件: </div> <div class="expandable-content" :class="{ expanded: isExpanded }"> <div v-for="(condition, index) in conditionsList" :key="condition.value" class="flex p-be-5 p-is-18.5 condition-box" > <a-input v-model:value="condition.label" disabled class="w-50" /> <template v-if="condition.type === 'DatePicker'"> <a-range-picker v-model:value="condition.keysDate" class="m-inline-2.5" /> </template> <template v-else-if="condition.type === 'NumberRange'"> <a-input-number id="inputNumber" v-model:value="condition.keys[0].isSys" class="m-inline-2.5" /> </template> <template v-else-if="condition.type === 'SelectOption'"> <div v-for="(keyItem, i) in condition.keys" :key="keyItem.key + i"> <a-select v-model:value="keyItem.isSys" class="m-inline-2.5" style="width: 180px"> <a-select-option v-for="item in getDefaultOptions(condition)" :key="item.value" :value="item.value"> {{ item.label }} </a-select-option> </a-select> </div> </template> <template v-else> <a-select v-model:value="condition.viewfilter" class="m-inline-2.5" style="width: 180px"> <a-select-option v-for="item in getDefaultOptions(condition)" :key="item.value" :value="item.value"> {{ item.label }} </a-select-option> </a-select> <!-- TODO 這里是一個輸入框,點擊出彈窗選數(shù)據(jù) --> <a-select v-model:value="condition.keysMul" class="m-inline-2.5" style="width: 180px" mode="multiple"> <a-select-option v-for="item in getKeysOptions()" :key="item.value" :value="item.value"> {{ item.label }} </a-select-option> </a-select> </template> <MinusCircleOutlined style="color: #888" @click="handleDelete(index)" /> </div> </div> <a-button @click="selectionConditionRef.handleOpen"> <template #icon> <PlusOutlined /> </template> 添加條件 </a-button> <div class="flex justify-between m-t-5"> <div> <a-button class="m-ie-6" type="primary" @click="handleSearch"> 篩選 </a-button> <a-button :loading="loading" @click="handleSave"> 保存篩選條件 </a-button> </div> <a-button class="float-right" type="link" @click="handleClear"> 清空 </a-button> </div> <a-divider> <a-button type="link" @click="handleCollapse"> {{ isExpanded ? '收起' : '展開' }} <component :is="isExpanded ? UpOutlined : DownOutlined" /> </a-button> </a-divider> </div> <SelectCondition ref="selectionConditionRef" @handle-ok="handleOk" /> </div> </template> <style lang="less" scoped> .condition-box { position: relative; &::before { content: " "; position: absolute; left: 0; top: -4px; height: 100%; width: 55px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAAoAQMAAABglfBLAAAABlBMVEXM09t2YyHaAAAAAXRSTlMAQObYZgAAABNJREFUGNNjYGBgcGCAgFGadBoAQZoKAavfri4AAAAASUVORK5CYII=) repeat; } &:last-child::before { top: -4px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAAoCAYAAABaW2IIAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACfSURBVHgB7dOxDcJQDIThs0lBQcEIRBQoBRIbEiYBNoEJXoFQaCBikBfDCFEUOXJ0X29Zf3GAg+frY5iAYsYYFxXjomJcVIyLinFRMS4qxkXFuKgYN4aU0hrOXOIEuBXL1QHOXOKy5ZPK4pyadgNHAieP5l2ryPH/8tJZ9+1zU6i21a68YiC3ze2rba0mpVm+970xg/tOiYiIiIiIaHo/tyUf6I0zVSMAAAAASUVORK5CYII=) top no-repeat; } } .expandable-content { max-height: 0; overflow: hidden; transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); opacity: 0; transform: translateY(-20px); margin-top: 0; visibility: hidden; &.expanded { max-height: 1000px; opacity: 1; transform: translateY(0); margin-top: 16px; visibility: visible; } } </style>
??4. 選擇條件-選擇條件彈窗組件added-condition/select-condition.vue ??
<script setup lang="ts"> import { reactive, ref } from 'vue' import { hexToRgba } from '~@/utils/hexToRgba' import { getConditionList } from '@/api/getting-clues/search-clues.ts' import type { Condition } from '@/api/interface/getting-clues' defineOptions({ name: 'SelectCondition', }) const emit = defineEmits(['handleOk']) const { token } = useAntdToken() const message = useMessage() const open = ref<boolean>(false) function handleOpen() { open.value = true } function handleCancel() { open.value = false } function handleOk() { if (state.selectedItemLabels.length === 0) { message.error('請選擇要添加的條件') } else { emit('handleOk', state.selectedItemLabels) open.value = false } } // search const searchValue = ref<string>('') function onSearch(searchValue: string) { console.log('use value', searchValue) // console.log('or use this.value', searchValue.value); } // 條件列表 const conditionList = ref<Condition.ConditionItem[]>([]) getConditionList().then((res) => { if (res.success) { conditionList.value = res.data } }) // 主條件分類鼠標移入和選中效果 /** * @constant hoveredMainIndices 鼠標移入的索引 * @constant selectedMainIndices 選中的索引 * @constant currentMainIndex 當前選中主條件index,用于獲取子條件列表 * @constant hoveredItemIndices 選中的子條件索引 * @constant selectedItemIndices 當前選中的子條件 * @constant selectedItemLabels 選擇的條件 */ interface State { hoveredMainIndices: Set<number> selectedMainIndices: Set<number> currentMainIndex: number hoveredItemIndices: Set<number> selectedItemIndices: Set<number> selectedItemLabels: Condition.ConditionItem[] } const state = reactive<State>({ hoveredMainIndices: new Set(), selectedMainIndices: new Set([0]), currentMainIndex: 0, hoveredItemIndices: new Set(), selectedItemIndices: new Set(), selectedItemLabels: [], }) function handleMainClick(index: number) { if (state.currentMainIndex === index) { return } state.selectedMainIndices.clear() state.selectedMainIndices.add(index) state.currentMainIndex = index } function isMainSelected(index: number) { return state.selectedMainIndices.has(index) } function handleMainHovered(index: number, isHovered: boolean) { if (isHovered) { state.hoveredMainIndices.add(index) } else { state.hoveredMainIndices.delete(index) } } function isMainHovered(index: number) { return state.hoveredMainIndices.has(index) } function activeMainStyle(index: number) { if (isMainSelected(index)) { return { color: token.value?.colorPrimary, backgroundColor: hexToRgba(token.value?.colorPrimary, 0.05), borderRight: `2px solid ${token.value?.colorPrimary}`, } } else { if (isMainHovered(index)) { return { backgroundColor: 'rgba(0, 0, 0, 0.06)', } } } } // 子條件列表 const conditionChildrenList = computed(() => { const c = conditionList.value.find((_, index) => state.currentMainIndex === index) return c?.children || [] }) function handleItemClick(item: Condition.ConditionItem) { const a = state.selectedItemLabels.find(i => i.value === item.value) if (!a) { if (state.selectedItemLabels.length === 10) { return message.error('一次最多選擇10項') } state.selectedItemLabels.push(item) } else { state.selectedItemLabels = state.selectedItemLabels.filter(i => i.value !== item.value) } } function isItemSelected(item: Condition.ConditionItem) { return (state.selectedItemLabels.findIndex(i => i.value === item.value) !== -1) } function handleItemHovered(index: number, isHovered: boolean) { if (isHovered) { state.hoveredItemIndices.add(index) } else { state.hoveredItemIndices.delete(index) } } function isItemHovered(index: number) { return state.hoveredItemIndices.has(index) } function activeItemStyle(index: number, item: Condition.ConditionItem) { if (isItemSelected(item)) { return { color: '#ffffff', backgroundColor: token.value?.colorPrimary, } } else { if (isItemHovered(index)) { return { color: token.value?.colorPrimary, backgroundColor: hexToRgba(token.value?.colorPrimary, 0.05), } } } } function reset() { const initState: State = { hoveredMainIndices: new Set(), selectedMainIndices: new Set([0]), currentMainIndex: 0, hoveredItemIndices: new Set(), selectedItemIndices: new Set(), selectedItemLabels: [], } Object.assign(state, initState) } defineExpose({ handleOpen, handleCancel, reset, }) </script> <template> <a-modal v-model:open="open" width="50vw" title="添加條件" @ok="handleOk"> <div> <!-- search --> <div> <a-input-search v-model:value="searchValue" class="w-full" placeholder="搜索條件名稱" enter-button="搜索" size="large" @search="onSearch" /> </div> <!-- main wrapper --> <div class="mt-5 flex"> <div class="w-1/5 h-[50vh] overflow-y-scroll scrollbar"> <div v-for="(item, index) in conditionList" :key="index" class="p-2 m-r-1 lh-6 cursor-pointer" :style="activeMainStyle(index)" @click="handleMainClick(index)" @mouseover="handleMainHovered(index, true)" @mouseleave="handleMainHovered(index, false)" > {{ item.label }} </div> </div> <div class="flex-1 p-l-8 h-[50vh] overflow-y-auto scrollbar"> <span v-for="(item, index) in conditionChildrenList" :key="index" class="inline-block m-2 p-inline-6 p-block-2 b-1 b-solid b-color-#e5e5e5 b-rd-2 cursor-pointer" :style="activeItemStyle(index, item)" @click="handleItemClick(item)" @mouseover="handleItemHovered(index, true)" @mouseleave="handleItemHovered(index, false)" > {{ item.label }} </span> </div> </div> </div> <template #footer> <div class="flex-between b-t-1 b-t-solid b-color-#e5e5e5 p-2"> <div> 已選擇<span class="p-inline-1" :style="{ color: token?.colorPrimary }">{{ state.selectedItemLabels.length }}</span>個條件(一次最多10個) </div> <div> <a-button key="back" @click="handleCancel"> 取消 </a-button> <a-button key="submit" type="primary" @click="handleOk"> 確定 </a-button> </div> </div> </template> </a-modal> </template> <style lang="less" scoped></style>
??5. 定義常量數(shù)據(jù)文件constant/index.ts ??
export const NavData = [ { i: 0, title: '添加條件', url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNzMzOTk3MzM3MjgwIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQ2NTM1IiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiPjxwYXRoIGQ9Ik01MTIgOTcuNTIzODFjMjI4LjkxMjc2MiAwIDQxNC40NzYxOSAxODUuNTYzNDI5IDQxNC40NzYxOSA0MTQuNDc2MTlzLTE4NS41NjM0MjkgNDE0LjQ3NjE5LTQxNC40NzYxOSA0MTQuNDc2MTlTOTcuNTIzODEgNzQwLjkxMjc2MiA5Ny41MjM4MSA1MTIgMjgzLjA4NzIzOCA5Ny41MjM4MSA1MTIgOTcuNTIzODF6IG0zNi41NzE0MjkgMTk1LjA0NzYxOWgtNzMuMTQyODU4djE4Mi44MzI3NjFMMjkyLjU3MTQyOSA0NzUuNDI4NTcxdjczLjE0Mjg1OGwxODIuODU3MTQyLTAuMDI0MzgxVjczMS40Mjg1NzFoNzMuMTQyODU4di0xODIuODU3MTQySDczMS40Mjg1NzF2LTczLjE0Mjg1OGgtMTgyLjg1NzE0MlYyOTIuNTcxNDI5eiIgcC1pZD0iNDY1MzYiIGZpbGw9IiNmZmZmZmYiPjwvcGF0aD48L3N2Zz4=', }, { i: 1, title: '熱門推薦', url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNzMzOTk2Mjc3MzUyIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQzNjIwIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiPjxwYXRoIGQ9Ik03NzAuMDE2IDMzMi43NjhsLTc3LjgyNCA3Ni44czAtMzA3LjItMjU5LjYxNi00MDkuNTY4YzAgMC0yNS45MiAyODEuNi0xNTUuNzQ0IDM4My45MzYtMTI5Ljc5MiAxMDIuNDY0LTM4OS40NCA0MDkuNTY4IDEyOS42OTYgNjM5Ljk2OCAwIDAtMjU5LjYxNi0yODEuNiA3Ny44MjQtNDg2LjMwNCAwIDAtMjUuOTIgMTAyLjMzNiAxMDMuODcyIDIwNC44IDEyOS44MjQgMTAyLjM2OCAwIDI4MS42IDAgMjgxLjZzNjIzLjAwOC0xNTMuNjMyIDE4MS43OTItNjkxLjIzMnoiIGZpbGw9IiNmZmZmZmYiIHAtaWQ9IjQzNjIxIj48L3BhdGg+PC9zdmc+', }, { i: 2, title: '已保存的篩選條件', url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNzM0MDU5ODUyOTg5IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjU0MTQiIGlkPSJteF9uXzE3MzQwNTk4NTI5OTAiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PHBhdGggZD0iTTQyNi42NjY2NjcgNzI1LjMzMzMzM2gxNzAuNjY2NjY2djE3MC42NjY2NjdoLTE3MC42NjY2NjZ6IiBwLWlkPSI1NDE1IiBmaWxsPSIjZmZmZmZmIj48L3BhdGg+PHBhdGggZD0iTTg1OC40NTMzMzMgMzcxLjYyNjY2N2wtMjA2LjA4LTIwNi4wOEExMjggMTI4IDAgMCAwIDU2MS45MiAxMjhINDI2LjY2NjY2N3YyNTZoMjEzLjMzMzMzM2E0Mi42NjY2NjcgNDIuNjY2NjY3IDAgMCAxIDAgODUuMzMzMzMzSDM4NGE0Mi42NjY2NjcgNDIuNjY2NjY3IDAgMCAxLTQyLjY2NjY2Ny00Mi42NjY2NjZWMTI4SDI1NmExMjggMTI4IDAgMCAwLTEyOCAxMjh2NTEyYTEyOCAxMjggMCAwIDAgMTI4IDEyOGg4NS4zMzMzMzN2LTE3MC42NjY2NjdhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzQtODUuMzMzMzMzaDE3MC42NjY2NjZhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzQgODUuMzMzMzMzdjE3MC42NjY2NjdoODUuMzMzMzMzYTEyOCAxMjggMCAwIDAgMTI4LTEyOHYtMzA1LjkyYTEyOCAxMjggMCAwIDAtMzcuNTQ2NjY3LTkwLjQ1MzMzM3oiIHAtaWQ9IjU0MTYiIGZpbGw9IiNmZmZmZmYiPjwvcGF0aD48L3N2Zz4=', }, ] export const JudgementCondition: { [key: string]: any } = { type: { operateState: [ { value: 'text', label: '等于任意一個', }, { value: 'select-eq', label: '等于', }, { value: 'select-in', label: '包含', }, { value: 'select-in-one', label: '包含任意一個', }, { value: 'select-not', label: '不包含', }, ], }, renderData: { existData: [ { value: 0, label: '無', }, { value: 1, label: '有', }, ], ifData: [ { value: 0, label: '否', }, { value: 1, label: '是', }, ], }, tag: { inTag: [ { value: 0, label: '機械', }, { value: 1, label: '器械', }, { value: 2, label: '設(shè)備', }, { value: 1, label: '重工', }, ], }, // 所有的類別匹配不上走默認 default: { default: [ { value: 0, label: '存續(xù)', }, { value: 1, label: '在業(yè)', }, ], }, }
??6. 類別json數(shù)據(jù)api/index.ts ??
// api 模擬接口 export function getConditionList(): Promise<ResData<Condition.ConditionItem[]>> { return new Promise((resolve) => { resolve(conditionList as unknown as ResData<Condition.ConditionItem[]>) }) }
數(shù)據(jù)json:
{ "errcode": 200, "errmsg": "操作成功", "data": [ { "value": "extraHot", "label": "常用", "children": [ { "value": "businessLocation", "label": "企業(yè)所在地", "children": null, "type": "MultiSelect", "keys": [ { "key": "type", "value": "area", "isSys": 0 }, { "key": "tag", "value": "inTag", "isSys": 0 } ], "checked": true, "alisKey": false, "viewfilter": "text", "tooltip": "", "certificateFlag": true, "normal": true, "intellectualPropertyFlag": true, "groupName": "" }, { "value": "mobile", "label": "有無手機", "children": null, "type": "SelectOption", "keys": [ { "key": "renderData", "value": "existData", "isSys": 1 } ], "checked": true, "alisKey": false, "viewfilter": "bool", "tooltip": "", "certificateFlag": true, "normal": true, "intellectualPropertyFlag": true, "groupName": "" }, { "value": "operateState", "label": "經(jīng)營狀態(tài)", "children": null, "type": "MultiSelect", "keys": [ { "key": "type", "value": "operateState", "isSys": 0 } ], "checked": true, "alisKey": false, "viewfilter": "select-eq", "tooltip": "", "certificateFlag": true, "normal": true, "intellectualPropertyFlag": true, "groupName": "" }, { "value": "companyName", "label": "企業(yè)名稱", "children": null, "type": "TextTags", "keys": [ { "key": "type", "value": "companyName", "isSys": 0 }, { "key": "tag", "value": "inTag", "isSys": 0 } ], "checked": true, "alisKey": true, "viewfilter": "text", "tooltip": "", "certificateFlag": true, "normal": true, "intellectualPropertyFlag": true, "groupName": "" } ], "type": "", "keys": [], "checked": true, "alisKey": false, "viewfilter": "", "tooltip": "", "certificateFlag": true, "normal": true, "intellectualPropertyFlag": true, "groupName": "" }, { "value": "industryInfo", "label": "企業(yè)基本信息", "children": [ { "value": "foundTime", "label": "成立日期", "children": null, "type": "DatePicker", "keys": [], "checked": true, "alisKey": false, "viewfilter": "timeRange", "tooltip": "", "certificateFlag": true, "normal": true, "intellectualPropertyFlag": true, "groupName": "基本信息" } ], "type": "", "keys": [], "checked": true, "alisKey": false, "viewfilter": "", "tooltip": "", "certificateFlag": true, "normal": true, "intellectualPropertyFlag": true, "groupName": "" } ], "success": true }
??7. 數(shù)據(jù)接口定義interface/index.ts ??
import type { Dayjs } from 'dayjs' export namespace Condition { export interface ChildKeys { key: string value: string isSys: number } export interface ConditionItem { label: string value: string type: string keys: ChildKeys[] keysDate?: [Dayjs, Dayjs] keysMul?: any[] children: ConditionItem[] checked: boolean viewfilter: string tooltip: string [key: string]: any } }
?? 4. 封裝實例缺點??
added-condition.vue
文件內(nèi)動態(tài)渲染UI組件代碼
UI的結(jié)構(gòu)是不可預(yù)知的,所以既然叫動態(tài),那么就需要修改以為動態(tài)組件。。。
到此這篇關(guān)于vue3自定義動態(tài)不同UI組件篩選框案例的文章就介紹到這了,更多相關(guān)vue3 動態(tài)組件篩選框內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue前端如何設(shè)置Cookie和鑒權(quán)問題詳解
這篇文章主要介紹了前端如何設(shè)置和使用Cookie,并對比了Cookie和Token在鑒權(quán)中的優(yōu)缺點,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-02-02Vue3初探之ref、reactive以及改變數(shù)組的值
在setup函數(shù)中,可以使用ref函數(shù)和reactive函數(shù)來創(chuàng)建響應(yīng)式數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Vue3初探之ref、reactive以及改變數(shù)組值的相關(guān)資料,需要的朋友可以參考下2022-09-09vue router-link 默認a標簽去除下劃線的實現(xiàn)
這篇文章主要介紹了vue router-link 默認a標簽去除下劃線的實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11