< script setup > import {dialogProps, dialogEmits, useDialog} from '../../composables/dialog' // 定义和组合 props emits const props = defineProps ({ ...dialogProps, // 其他props const emits = defineEmits ([ ...dialogEmits, // 其他事件 const {visibleModel} = useDialog (props, emits) </ script >

一个最简单的组合就完成了.

useForm

1. 定义Form组合

import {ref} from 'vue'
// 修改了vaildate方法的Form组件, 之前的validate方法不管校验失败和成功都进到then里面,我觉得不好就改成只有校验成功才进then里面
export {bbForm as Form} from '../components/bb-form'
export {Input} from '@arco-design/web-vue'
export {InputNumber} from '@arco-design/web-vue'
export function useForm (key) {
  // 需要在模板上定义 <a-form ref="ref_form">
  const ref_form = ref(null)
  return {
    ref_form

2. 使用Form组合

<template>
    <bb.Form ref="ref_form" :model="form">
    </bb.Form>
</template>
<script setup>
import * as bb from '../../composables/form'
const form = ref({
  name: ''
const {ref_form} = bb.useForm()
// 使用ref_form.value.validate验证表单
</script>

useFormInDialog

如果有这样一个需求, 弹框里加上表单,需要提交一些信息,需要先表单验证再提交.失败不关闭表单,成功后关闭表单. 就可以把上面定义的组合再组合一下.

1.定义useFormInDialog组合

import {ref} from 'vue'
import {Message} from '@arco-design/web-vue'
import {getErrorMessageContent} from '../utils/utils'
// visibleModel 是 useDialog 定义的
// ref_form 是 useForm 定义的
export function useFormInDialog (promise, visibleModel, ref_form = null) {
  // 需要控制的表单提交按钮的loading状态
  const okLoading = ref(false)
  // 使用beforeOk这个方式来控制弹框的显示关闭状态
  function beforeOk (done) {
    let validatePromise = ref_form ? ref_form.value.bbValidate() : Promise.resolve()
    validatePromise
      .then(() => {
        okLoading.value = true
        promise()
          .then(() => {
            okLoading.value = false
            Message.success('操作成功!')
            done()
            visibleModel ? visibleModel.value = false : ''
          .catch(err => {
            okLoading.value = false
            if (Array.isArray(err) && err[0].name === 'ValidateError') {
            } else {
              Message.error(getErrorMessageContent(err))
      .catch(err => {
        console.warn('表单校验失败!', err)
        okLoading.value = false
    return false
  return {
    okLoading,
    beforeOk

2.使用useFormInDialog组合

<template>
  <a-modal 
    v-model:visible="visibleModel" // Dialog 组合
    :ok-loading="okLoading" // FormInDialog 组合
    @before-ok="beforeOk" // FormInDialog 组合
    <template #title>查看和编辑</template>
    <bb.Form ref="ref_form" :model="form"> // Form 组合
      // 具体表单组件
    </bb.Form>
  </a-modal>
</template>
<script setup>
import axios from 'axios'
import {inject, ref, reactive} from 'vue'
import * as bb from '../../composables/form'
import {dialogProps, dialogEmits, useDialog} from '../../composables/dialog'
import {useFormInDialog} from '../../composables/form-dialog'
// Dialog组合
const props = defineProps({
  ...dialogProps,
  uuid: {
    type: String,
    required: true
const emits = defineEmits([
    ...dialogEmits,
    'edit-success'
const {visibleModel} = useDialog(props, emits)
// Form组合
const form = ref({
const rules = reactive({
const {ref_form} = bb.useForm()
// FormInDialog组合
// 只需要定义好表单的校验规则,只要写少量的业务代码就能完成复用
const {okLoading, beforeOk} = useFormInDialog(() => {
  return new Promise(async (resolve, reject) => {
    try {
      await axios.put(`具体api`, {...form.value})
      resolve()
      emits('edit-success')
    } catch (err) {
      reject(err)
}, visibleModel, ref_form)
</script>

组合之后的代码比我之前写vue2的时候更紧凑了. 在如何写业务代码的时候更多了一些思考.

分类:
前端