使用Vue3和antd的Modal组件封装一个useDialog hooks

862 阅读1分钟

这篇文章主要介绍了使用 Vue3 和 antd 的 Modal 组件封装的一个 useDialog hooks。包括其函数内部定义的各种变量和处理逻辑,如 confirmLoadingvisible 等。还展示了传入的组件、组件属性及调用实例,如定义了子组件的模板、脚本和样式,以及如何在实际中调用 useDialog 并传递相关参数。

image.png

useDialog hooks内容主体

import { createVNode, defineComponent, ref, render } from 'vue'
import AppProvider from '@/components/app-provider/index.vue' //用于同步国际化和主题的组件
import { BasicModal } from '@/components/basic-modal' //自定义modal组件

function useDialog({ component, componentProps = {}, modalProps = {}, callback }) {
  const confirmLoading = ref(modalProps.confirmLoading || false);
  const visible = ref(true);
  const componentRef = ref(null);

  const handleClose = async () => {
    confirmLoading.value = true;
    try {
      if (componentRef.value?.onCancel) {
        await componentRef.value.onCancel();
      }
    }
    catch (error) {
      console.error(error);
    }
    finally {
      confirmLoading.value = false;
      visible.value = false;
      close()
    }
  };

  const handleOk = async () => {
    confirmLoading.value = true;
    try {
      let res;
      if (componentRef.value?.onOk) {
        res = await componentRef.value.onOk();
      }
      visible.value = false;
      callback && callback(res);
    }
    catch (error) {
      console.error(error);
    }
    finally {
      confirmLoading.value = false;
    }
  };

  const DialogWrapper = defineComponent({
    setup() {
      return () =>
        createVNode(AppProvider, {}, {
          default: () => createVNode(
            BasicModal,
            {
              open: visible.value,
              'onUpdate:open': val => (visible.value = val),
              confirmLoading: confirmLoading.value,
              okText: '确定',
              cancelText: '取消',
              onOk: handleOk,
              onCancel: handleClose,
              destroyOnClose: true,
              ...modalProps,
            },
            {
              default: () =>
                createVNode(component, {
                  ...componentProps,
                  ref: componentRef,
                }),
              ...modalProps.slots,
            },
          ),
        })
    },
  });
  const vm = createVNode(DialogWrapper)
  function close() {
    if (vm?.el && vm.el.parentNode) {
      vm.el.parentNode.removeChild(vm.el);
    }
  }
  render(vm, document.createElement('div'));
  //通过componentRef可以获取到传入的子组件的实例,需要访问子组件的方法或者变量,主要在子组件从使用defineExpose暴露出来
  return {
     componentRef:componentRef.value
    }

export default useDialog

传入hooks的component

<template>
  <div>{{ message }}</div>
</template>

<script setup>
const props = defineProps({
  message: {
    type: String,
    default: '我是子组件的message',
  },
})
const onOk = () => {
  console.log('我是子组件的ok事件')
  return new Promise(resolve => setTimeout(resolve, 1000))
}
const onCancel = () => {
  console.log('我是子组件的cancel事件')
}
defineExpose({ onOk, onCancel })
</script>

<style lang="less" scoped></style>

调用hooks实例

const { componentRef } = useDialog(
    {
      component: updatePassWord, // 传入组件
      componentProps: {
        id: formState.value.userId,
      }, // componentProps 传递给内容组件的属性
      modalProps: {
        title: '修改密码',
      }, // modalProps 其他Modal组件的属性
    },
  )