wip(VForm): VForm component development

This commit is contained in:
陈凯龙 2021-12-17 15:10:39 +08:00
parent 69909e2832
commit d9d64f3931
6 changed files with 144 additions and 52 deletions

View File

@ -39,6 +39,27 @@ onMounted(() => {
restaurants.value = loadAll() restaurants.value = loadAll()
}) })
const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
const options = ref<FormOptions[]>(
Array.from({ length: 1000 }).map((_, idx) => ({
value: `Option ${idx + 1}`,
label: `${initials[idx % 10]}${idx}`
}))
)
const options2 = ref<FormOptions[]>(
Array.from({ length: 10 }).map((_, idx) => {
const label = idx + 1
return {
value: `Group ${label}`,
label: `Group ${label}`,
options: Array.from({ length: 10 }).map((_, idx) => ({
value: `Option ${idx + 1 + 10 * label}`,
label: `${initials[idx % 10]}${idx + 1 + 10 * label}`
}))
}
})
)
const schema = reactive<VFormSchema[]>([ const schema = reactive<VFormSchema[]>([
{ {
field: 'field1', field: 'field1',
@ -238,6 +259,45 @@ const schema = reactive<VFormSchema[]>([
} }
], ],
optionsSlot: true optionsSlot: true
},
{
field: 'field17',
label: `${t('formDemo.selectV2')}`,
component: 'Divider'
},
{
field: 'field18',
label: t('formDemo.default'),
component: 'SelectV2',
options: options.value
},
{
field: 'field18',
label: t('formDemo.slot'),
component: 'SelectV2',
options: options.value,
componentProps: {
slots: {
default: true
}
}
},
{
field: 'field19',
label: t('formDemo.group'),
component: 'SelectV2',
options: options2.value
},
{
field: 'field20',
label: `${t('formDemo.group')}${t('formDemo.slot')}`,
component: 'SelectV2',
options: options2.value,
componentProps: {
slots: {
default: true
}
}
} }
]) ])
</script> </script>
@ -260,18 +320,32 @@ const schema = reactive<VFormSchema[]>([
<span class="link">{{ item.link }}</span> <span class="link">{{ item.link }}</span>
</template> </template>
<template #field14-option="item"> <template #field14-option="{ item }">
<span style="float: left">{{ item.label }}</span> <span style="float: left">{{ item.label }}</span>
<span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">{{ <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
item.value {{ item.value }}
}}</span> </span>
</template> </template>
<template #field16-option="item"> <template #field16-option="{ item }">
<span style="float: left">{{ item.label }}</span> <span style="float: left">{{ item.label }}</span>
<span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">{{ <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
item.value {{ item.value }}
}}</span> </span>
</template>
<template #field18-default="{ item }">
<span style="float: left">{{ item.label }}</span>
<span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
{{ item.value }}
</span>
</template>
<template #field20-default="{ item }">
<span style="float: left">{{ item.label }}</span>
<span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
{{ item.value }}
</span>
</template> </template>
</VFrom> </VFrom>
</ElConfigProvider> </ElConfigProvider>

View File

@ -1,10 +1,11 @@
<script lang="tsx"> <script lang="tsx">
import { PropType, defineComponent, ref, computed, unref } from 'vue' import { PropType, defineComponent, ref, computed, unref } from 'vue'
import { ElForm, ElFormItem, ElRow, ElCol, ElOption, ElOptionGroup } from 'element-plus' import { ElForm, ElFormItem, ElRow, ElCol } from 'element-plus'
import { componentMap } from './componentMap' import { componentMap } from './componentMap'
import { propTypes } from '@/utils/propTypes' import { propTypes } from '@/utils/propTypes'
import { getSlot } from '@/utils/tsxHelper' import { getSlot } from '@/utils/tsxHelper'
import { setTextPlaceholder, setGridProp, setComponentProps, setItemComponentSlots } from './helper' import { setTextPlaceholder, setGridProp, setComponentProps, setItemComponentSlots } from './helper'
import { useRenderSelect } from './components/useRenderSelect'
export default defineComponent({ export default defineComponent({
name: 'VForm', name: 'VForm',
@ -74,9 +75,12 @@ export default defineComponent({
<Com <Com
{...(autoSetPlaceholder && setTextPlaceholder(item))} {...(autoSetPlaceholder && setTextPlaceholder(item))}
{...setComponentProps(item.componentProps)} {...setComponentProps(item.componentProps)}
// SelectV2
options={item.component === 'SelectV2' ? item.options || [] : undefined}
> >
{{ {{
default: () => (item.options ? renderOptions(item) : null), default: () =>
item.options && item.component !== 'SelectV2' ? renderOptions(item) : undefined,
...setItemComponentSlots(slots, item?.componentProps?.slots, item.field) ...setItemComponentSlots(slots, item?.componentProps?.slots, item.field)
}} }}
</Com> </Com>
@ -90,52 +94,13 @@ export default defineComponent({
function renderOptions(item: VFormSchema) { function renderOptions(item: VFormSchema) {
switch (item.component) { switch (item.component) {
case 'Select': case 'Select':
const { renderSelectOptions } = useRenderSelect(slots)
return renderSelectOptions(item) return renderSelectOptions(item)
default: default:
break break
} }
} }
// select options
function renderSelectOptions(item: VFormSchema) {
//
const labelAlias = item.optionsField?.labelField
return item.options?.map((option) => {
if (option?.options?.length) {
return (
<ElOptionGroup label={labelAlias ? option[labelAlias] : option['label']}>
{() => {
return option?.options?.map((v) => {
return renderSelectOptionItem(item, v)
})
}}
</ElOptionGroup>
)
} else {
return renderSelectOptionItem(item, option)
}
})
}
// select option item
function renderSelectOptionItem(item: VFormSchema, option: FormOptions) {
//
const labelAlias = item.optionsField?.labelField
const valueAlias = item.optionsField?.valueField
return (
<ElOption
label={labelAlias ? option[labelAlias] : option['label']}
value={valueAlias ? option[valueAlias] : option['value']}
>
{{
default: () =>
// option {field}-option
item.optionsSlot ? getSlot(slots, `${item.field}-option`, option) : null
}}
</ElOption>
)
}
// Form // Form
function getFormBindValue() { function getFormBindValue() {
// //

View File

@ -0,0 +1,49 @@
import { ElOption, ElOptionGroup } from 'element-plus'
import { getSlot } from '@/utils/tsxHelper'
import { Slots } from 'vue'
export function useRenderSelect(slots: Slots) {
// 渲染 select options
function renderSelectOptions(item: VFormSchema) {
// 如果有别名,就取别名
const labelAlias = item.optionsField?.labelField
return item.options?.map((option) => {
if (option?.options?.length) {
return (
<ElOptionGroup label={labelAlias ? option[labelAlias] : option['label']}>
{() => {
return option?.options?.map((v) => {
return renderSelectOptionItem(item, v)
})
}}
</ElOptionGroup>
)
} else {
return renderSelectOptionItem(item, option)
}
})
}
// 渲染 select option item
function renderSelectOptionItem(item: VFormSchema, option: FormOptions) {
// 如果有别名,就取别名
const labelAlias = item.optionsField?.labelField
const valueAlias = item.optionsField?.valueField
return (
<ElOption
label={labelAlias ? option[labelAlias] : option['label']}
value={valueAlias ? option[valueAlias] : option['value']}
>
{{
default: () =>
// option 插槽名规则,{field}-option
item.optionsSlot ? getSlot(slots, `${item.field}-option`, { item: option }) : undefined
}}
</ElOption>
)
}
return {
renderSelectOptions
}
}

View File

@ -117,3 +117,5 @@ export function setItemComponentSlots(
} }
return slotObj return slotObj
} }
export function setModel() {}

View File

@ -16,6 +16,7 @@ export default {
position: 'Position', position: 'Position',
autocomplete: 'Autocomplete', autocomplete: 'Autocomplete',
select: 'Select', select: 'Select',
group: 'Select Group' group: 'Select Group',
selectV2: 'SelectV2'
} }
} }

View File

@ -16,6 +16,7 @@ export default {
position: '位置', position: '位置',
autocomplete: '自动补全', autocomplete: '自动补全',
select: '选择器', select: '选择器',
group: '选项分组' group: '选项分组',
selectV2: '虚拟列表选择器'
} }
} }