Skip to content

useFormLayout

函数式弹窗/抽屉,通过 open() 方法即可弹出模态框,支持嵌入 DataForm 表单或任意自定义内容,内置表单校验和提交流程。

ts
import { useFormLayout } from 'yoyoo-ui'

在线演示

tsx
import { defineComponent, defineAsyncComponent } from 'vue'

// 异步加载内层组件,避免 SSR 中 useFormLayout 调用 DOM API 报错
const AsyncDemo = defineAsyncComponent(() => import('./_inner/UseFormLayoutInner.tsx'))

export default defineComponent({
  name: 'DemoUseFormLayoutBasic',
  setup() {
    return () => <AsyncDemo />
  },
})

实际逻辑在 _inner/UseFormLayoutInner.tsx 中:

tsx
import { defineComponent, h } from 'vue'
import { ElButton, ElTag, ElMessage } from 'element-plus'
import { useFormLayout } from '@/components/FormLayout'

export default defineComponent({
  name: 'UseFormLayoutInner',
  setup() {
    const formModal = useFormLayout()
    const contentDrawer = useFormLayout()

    const openFormModal = () => {
      formModal.open({
        title: '编辑用户',
        type: 'modal',
        size: 'sm',
        form: {
          model: { name: '张三', role: 'admin' },
          columns: [
            { field: 'name', label: '姓名', required: true },
            {
              field: 'role',
              label: '角色',
              type: 'data-picker',
              props: {
                type: 'select',
                options: [
                  { label: '管理员', value: 'admin' },
                  { label: '编辑者', value: 'editor' },
                ],
              },
            },
          ],
        },
        onConfirm: async ({ form: data }) => {
          ElMessage.success('提交:' + JSON.stringify(data))
        },
      })
    }

    const openContentDrawer = () => {
      contentDrawer.open({
        title: '详情信息',
        type: 'drawer',
        size: 'sm',
        content: () =>
          h('div', { style: 'padding: 20px; line-height: 2;' }, [
            h('h3', { style: 'margin-bottom: 16px;' }, '订单 #20240722001'),
            h('p', ['状态:', h(ElTag, { type: 'success' }, '已完成')]),
            h('p', '金额:¥ 1,280.00'),
            h('p', '收货地址:北京市朝阳区建国路 88 号'),
            h('p', '下单时间:2024-07-22 14:30:00'),
          ]),
        onConfirm: async () => {
          ElMessage.success('已确认')
        },
      })
    }

    return () => (
      <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
        <ElButton type="primary" onClick={openFormModal}>
          表单弹窗
        </ElButton>
        <ElButton onClick={openContentDrawer}>
          自定义内容抽屉
        </ElButton>
      </div>
    )
  },
})

基本用法

ts
const form = useFormLayout()

form.open({
  title: '编辑用户',
  type: 'modal',          // 'modal' | 'drawer'
  size: 'md',             // 'sm' | 'md' | 'l' | 'lg' | 'xlg'
  form: {
    model: { id: 1, name: '张三' },
    columns: [
      { field: 'name', label: '姓名' },
    ],
  },
  onConfirm: async ({ form: data }) => {
    await saveUser(data)
  },
})

LayoutModalOptions

属性类型默认值说明
titlestring弹窗标题
type'modal' | 'drawer''modal'弹窗类型
size'sm' | 'md' | 'l' | 'lg' | 'xlg''md'尺寸(对应 400/800/1000/1200/1400px)
widthnumber自定义宽度(px),优先于 size
formFormPropsDataForm 配置
contentVNode | () => VNode自定义内容(与 form 共存)
onConfirm({ form, content }) => Promise确认回调
onCancel() => void取消回调
buttonsButtonProps[]自定义按钮组
showButtonbooleantrue是否显示底部按钮
propsRecord<string, any>透传 ElDialog / ElDrawer 属性

返回值

方法签名说明
open(options?: LayoutModalOptions) => void打开弹窗/抽屉
close() => void关闭
confirm() => Promise<void>触发表单校验并执行 onConfirm
cancel() => void触发 onCancel 并关闭
validate() => Promise<{ form, content }>手动校验表单及 content