vue中如何封装弹窗组件才能使项目更好维护

本文探讨了在Vue项目中如何封装弹窗组件以提高代码可维护性。业务场景涉及数据编辑、选择和确认操作。两种实现方案被提出:1) 将弹窗及其内容封装为组件,通过open方法返回promise;2) 通过visible属性控制弹窗,并监听confirm和cancel事件。然而,第二种方法的缺点是父组件需管理可见状态,且操作分散,影响业务理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

业务场景:

弹窗一般用于数据编辑、数据选择和动作确认,归纳而言就是作为某个流程的中间环节

已知实现方案和优劣:

1.(暂定)把弹窗及内容封装为一个组件,该组件暴露一个返回 promise 的 open 方法来打开弹窗。代码如下:

  • 父组件中使用封装好的弹窗组件 CustomersDetail.vue
<template>
  <div>
    <el-button @click="addCustomers">新增客户</el-button>
    <CustomersDetail ref="customersDetail"></CustomersDetail>
  </div>
</template>
<script>
import { defineComponent, ref } from '@vue/composition-api'
import CustomersDetail from './CustomersDetail.vue'

export default defineComponent({
  components: { CustomersDetail },
  setup() {
    const customersDetail = ref(null)
    const addCustomers = async () => {
      const customersData = await customersDetail.value.open()
      // ...doSome
    }
    return {
      addCustomers,
      customersDetail
    }
  }
})
</script>
  • 弹窗组件 CustomersDetail.vue 中使用 useDialog
<!-- CustomersDetail.vue -->
<template>
  <el-dialog title="新增客户" :visible="visible" v-loading="loading" append-to-body id="app" @close="cancel" center>
    <el-form :model="formData">
      <el-col span="8">
        <el-form-item label="客户姓名:">
          <el-input v-model="formData.customerName"></el-input>
        </el-form-item>
      </el-col>
      <el-col span="8">
        <el-form-item label="客户电话:">
          <el-input v-model="formData.customerPhone"></el-input>
        </el-form-item>
      </el-col>
      <el-col span="8">
        <el-form-item label="客户邮箱:">
          <el-input v-model="formData.customerEmail"></el-input>
        </el-form-item>
      </el-col>
    </el-form>
    <span slot="footer">
      <el-button type="primary" @click="confirm(formData)">确认</el-button>
      <el-button type="primary" @click="cancel">取消</el-button>
    </span>
  </el-dialog>
</template>
<script>
import { defineComponent, reactive } from '@vue/composition-api'
import { useDialog } from './useDialog'
function initFormData() {
  return {
    customerName: '',
    customerPhone: '',
    customerEmail: ''
  }
}

export default defineComponent({
  setup() {
    const { visible, openFactory, loading, confirm, cancel } = useDialog()
    const formData = reactive(initFormData())
    const open = openFactory((params) => {
      Object.assign(formData, initFormData(), params)
    })
    return {
      confirm,
      visible,
      loading,
      cancel,
      formData,
      open
    }
  }
})
</script>
 
  • 封装弹窗公共逻辑为 useDialog
export const useDialog = () => {
  const visible = ref(false)
  const openFactory = (init) => {
    return (params) => {
      return new Promise(async (resolve, reject) => {
        visible.value = true
        loading.value = true
        await init(params)
        loading.value = false
        resolveFun = resolve
      })
    }
  }
  let resolveFun
  const loading = ref(false)
  const confirm = (dialogData) => {
    visible.value = false
    resolveFun(dialogData)
  }
  const cancel = () => {
    visible.value = false
    resolveFun(null)
  }
  return {
    visible,
    openFactory,
    loading,
    confirm,
    cancel
  }
}

2.采用传入 visible 打开弹窗,监听 confirm 和 cancel 事件获取用户操作的结果

  • 缺点:
    • 在父组件需要定义并操作 visible 状态
    • 打开弹窗的动作和后续的行为位于两个独立函数中,不利于业务理解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值