perf: 优化Form事件传递

This commit is contained in:
kailong321200875 2023-06-27 09:49:07 +08:00
parent 24c8af9183
commit 69cafb3b7b
6 changed files with 53 additions and 228 deletions

View File

@ -1,6 +1,6 @@
<script lang="tsx">
import { PropType, defineComponent, ref, computed, unref, watch, onMounted } from 'vue'
import { ElForm, ElFormItem, ElRow, ElCol } from 'element-plus'
import { ElForm, ElFormItem, ElRow, ElCol, FormItemProp } from 'element-plus'
import { componentMap } from './helper/componentMap'
import { propTypes } from '@/utils/propTypes'
import { getSlot } from '@/utils/tsxHelper'
@ -57,7 +57,7 @@ export default defineComponent({
// label
labelWidth: propTypes.oneOfType([String, Number]).def('auto')
},
emits: ['register'],
emits: ['register', 'validate'],
setup(props, { slots, expose, emit }) {
// element form
const elFormRef = ref<ComponentRef<typeof ElForm>>()
@ -339,12 +339,17 @@ export default defineComponent({
return props
}
const onValidate = (prop: FormItemProp, isValid: boolean, message: string) => {
emit('validate', prop, isValid, message)
}
return () => (
<ElForm
ref={elFormRef}
{...getFormBindValue()}
model={unref(getProps).isCustom ? unref(getProps).model : formModel}
class={prefixCls}
onValidate={onValidate}
>
{{
//

View File

@ -8,6 +8,7 @@ import { cloneDeep, set } from 'lodash-es'
import { initModel } from '@/components/Form/src/helper'
import ActionButton from './components/ActionButton.vue'
import { SearchProps } from './types'
import { FormItemProp } from 'element-plus'
const props = defineProps({
// Form
@ -42,7 +43,7 @@ const props = defineProps({
resetLoading: propTypes.bool.def(false)
})
const emit = defineEmits(['search', 'reset', 'register'])
const emit = defineEmits(['search', 'reset', 'register', 'validate'])
const visible = ref(true)
@ -214,6 +215,10 @@ onMounted(() => {
})
defineExpose(defaultExpose)
const onFormValidate = (prop: FormItemProp, isValid: boolean, message: string) => {
emit('validate', prop, isValid, message)
}
</script>
<template>
@ -226,6 +231,7 @@ defineExpose(defaultExpose)
:is-col="getProps.isCol"
:schema="newSchema"
@register="formRegister"
@validate="onFormValidate"
/>
<template v-if="layout === 'bottom'">

View File

@ -182,7 +182,7 @@ export default defineComponent({
) : undefined
}
const rnderTreeTableColumn = (columnsChildren: TableColumn[]) => {
const renderTreeTableColumn = (columnsChildren: TableColumn[]) => {
const { align, headerAlign, showOverflowTooltip } = unref(getProps)
return columnsChildren.map((v) => {
const props = { ...v }
@ -198,7 +198,7 @@ export default defineComponent({
{{
default: (data: TableSlotDefault) =>
v.children && v.children.length
? rnderTableColumn(v.children)
? renderTableColumn(v.children)
: // @ts-ignore
getSlot(slots, v.field, data) ||
v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
@ -211,7 +211,7 @@ export default defineComponent({
})
}
const rnderTableColumn = (columnsChildren?: TableColumn[]) => {
const renderTableColumn = (columnsChildren?: TableColumn[]) => {
const {
columns,
reserveIndex,
@ -253,7 +253,7 @@ export default defineComponent({
{{
default: (data: TableSlotDefault) =>
v.children && v.children.length
? rnderTreeTableColumn(v.children)
? renderTreeTableColumn(v.children)
: // @ts-ignore
getSlot(slots, v.field, data) ||
v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
@ -278,7 +278,7 @@ export default defineComponent({
{...unref(getBindValue)}
>
{{
default: () => rnderTableColumn(),
default: () => renderTableColumn(),
// @ts-ignore
append: () => getSlot(slots, 'append')
}}

View File

@ -159,42 +159,34 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
}
]
},
// {
// path: 'table',
// component: getParentLayout(),
// redirect: '/components/table/default-table',
// name: 'TableDemo',
// meta: {
// title: t('router.table'),
// alwaysShow: true
// },
// children: [
// {
// path: 'default-table',
// component: () => import('@/views/Components/Table/DefaultTable.vue'),
// name: 'DefaultTable',
// meta: {
// title: t('router.defaultTable')
// }
// },
// {
// path: 'use-table',
// component: () => import('@/views/Components/Table/UseTableDemo.vue'),
// name: 'UseTable',
// meta: {
// title: 'UseTable'
// }
// },
// {
// path: 'ref-table',
// component: () => import('@/views/Components/Table/RefTable.vue'),
// name: 'RefTable',
// meta: {
// title: 'RefTable'
// }
// }
// ]
// },
{
path: 'table',
component: getParentLayout(),
redirect: '/components/table/default-table',
name: 'TableDemo',
meta: {
title: t('router.table'),
alwaysShow: true
},
children: [
{
path: 'default-table',
component: () => import('@/views/Components/Table/DefaultTable.vue'),
name: 'DefaultTable',
meta: {
title: t('router.defaultTable')
}
}
// {
// path: 'use-table',
// component: () => import('@/views/Components/Table/UseTableDemo.vue'),
// name: 'UseTable',
// meta: {
// title: 'UseTable'
// }
// }
]
},
{
path: 'editor-demo',
component: getParentLayout(),

View File

@ -4,7 +4,7 @@ import { ContentWrap } from '@/components/ContentWrap'
import { useI18n } from '@/hooks/web/useI18n'
import { useForm } from '@/hooks/web/useForm'
import { reactive, unref, ref } from 'vue'
import { ElButton, ElInput } from 'element-plus'
import { ElButton, ElInput, FormItemProp } from 'element-plus'
import { useValidator } from '@/hooks/web/useValidator'
import { getDictOneApi } from '@/api/common'
@ -257,6 +257,10 @@ const inoutValidation = async () => {
console.log(val)
})
}
const formValidate = (prop: FormItemProp, isValid: boolean, message: string) => {
console.log(prop, isValid, message)
}
</script>
<template>
@ -301,7 +305,7 @@ const inoutValidation = async () => {
</ElButton>
</ContentWrap>
<ContentWrap :title="`UseForm ${t('formDemo.example')}`">
<Form :schema="schema" @register="formRegister" />
<Form :schema="schema" @register="formRegister" @validate="formValidate" />
</ContentWrap>
</template>

View File

@ -1,182 +0,0 @@
<script setup lang="ts">
import { ContentWrap } from '@/components/ContentWrap'
import { useI18n } from '@/hooks/web/useI18n'
import { Table, TableExpose } from '@/components/Table'
import { getTableListApi } from '@/api/table'
import { TableData } from '@/api/table/types'
import { ref, h, reactive, unref } from 'vue'
import { ElTag, ElButton } from 'element-plus'
import { useTable } from '@/hooks/web/useTable'
import { Pagination, TableColumn, TableSlotDefault } from '@/types/table'
const { t } = useI18n()
const columns = reactive<TableColumn[]>([
{
field: 'index',
label: t('tableDemo.index'),
type: 'index'
},
{
field: 'content',
label: t('tableDemo.header'),
children: [
{
field: 'title',
label: t('tableDemo.title')
},
{
field: 'author',
label: t('tableDemo.author')
},
{
field: 'display_time',
label: t('tableDemo.displayTime')
},
{
field: 'importance',
label: t('tableDemo.importance'),
formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
return h(
ElTag,
{
type: cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'
},
() =>
cellValue === 1
? t('tableDemo.important')
: cellValue === 2
? t('tableDemo.good')
: t('tableDemo.commonly')
)
}
},
{
field: 'pageviews',
label: t('tableDemo.pageviews')
}
]
},
{
field: 'action',
label: t('tableDemo.action')
}
])
const { register, tableObject, methods } = useTable<TableData>({
getListApi: getTableListApi,
response: {
list: 'list',
total: 'total'
},
props: {
columns
}
})
const { getList } = methods
getList()
const tableRef = ref<TableExpose>()
const actionFn = (data: TableSlotDefault) => {
console.log(data)
}
const paginationObj = ref<Pagination>()
const showPagination = (show: boolean) => {
if (show) {
paginationObj.value = {
total: tableObject.total
}
} else {
paginationObj.value = undefined
}
}
const reserveIndex = (custom: boolean) => {
unref(tableRef)?.setProps({
reserveIndex: custom
})
}
const showSelections = (show: boolean) => {
unref(tableRef)?.setProps({
selection: show
})
}
const index = ref(1)
const changeTitle = () => {
unref(tableRef)?.setColumn([
{
field: 'title',
path: 'label',
value: `${t('tableDemo.title')}${unref(index)}`
}
])
index.value++
}
const showExpandedRows = (show: boolean) => {
unref(tableRef)?.setProps({
expand: show
})
}
const selectAllNone = () => {
unref(tableRef)?.elTableRef?.toggleAllSelection()
}
</script>
<template>
<ContentWrap :title="`RefTable ${t('tableDemo.operate')}`">
<ElButton @click="showPagination(true)">
{{ t('tableDemo.show') }} {{ t('tableDemo.pagination') }}
</ElButton>
<ElButton @click="showPagination(false)">
{{ t('tableDemo.hidden') }} {{ t('tableDemo.pagination') }}
</ElButton>
<ElButton @click="reserveIndex(true)">{{ t('tableDemo.reserveIndex') }}</ElButton>
<ElButton @click="reserveIndex(false)">{{ t('tableDemo.restoreIndex') }}</ElButton>
<ElButton @click="showSelections(true)">{{ t('tableDemo.showSelections') }}</ElButton>
<ElButton @click="showSelections(false)">{{ t('tableDemo.hiddenSelections') }}</ElButton>
<ElButton @click="changeTitle">{{ t('tableDemo.changeTitle') }}</ElButton>
<ElButton @click="showExpandedRows(true)">{{ t('tableDemo.showExpandedRows') }}</ElButton>
<ElButton @click="showExpandedRows(false)">{{ t('tableDemo.hiddenExpandedRows') }}</ElButton>
<ElButton @click="selectAllNone">{{ t('tableDemo.selectAllNone') }}</ElButton>
</ContentWrap>
<ContentWrap :title="`RefTable ${t('tableDemo.example')}`">
<Table
ref="tableRef"
v-model:pageSize="tableObject.pageSize"
v-model:currentPage="tableObject.currentPage"
:data="tableObject.tableList"
:loading="tableObject.loading"
:pagination="paginationObj"
@register="register"
>
<template #action="data">
<ElButton type="primary" @click="actionFn(data as TableSlotDefault)">
{{ t('tableDemo.action') }}
</ElButton>
</template>
<template #expand="data">
<div class="ml-30px">
<div>{{ t('tableDemo.title') }}{{ data.row.title }}</div>
<div>{{ t('tableDemo.author') }}{{ data.row.author }}</div>
<div>{{ t('tableDemo.displayTime') }}{{ data.row.display_time }}</div>
</div>
</template>
</Table>
</ContentWrap>
</template>