Ant Design Vue 之可拖拽对话框

最近在工作中需要实现个功能,希望通过右键菜单的方式打开对话框的功能,且需要支持拖拽功能。因为使用的前端组件是Ant Design Vue,所以在其官网上找了半天都没找到示例,终于在网上又找了半天给我找到了个实现方式(不好意思忘记是哪个博主的文章了),虽然可能有点绕,但总归是能实现需求了。现记录实现方式,希望对各位有所帮助。

​ 总体思路为,通过包装a-modal组件的方式定义出一个虚拟弹出框组件(支持拖动),虚拟组件监听pinia中属性的状态变化来实现打开与关闭。此组件在全局页面上注册,需要打开时改变pinia中的状态值即可。虚拟弹出框组件详细步骤如下:

  1. template

    <a-modal v-model:open="popoverInfo.visible" :wrap-style="{ overflow: 'hidden' }" :style="modalStyle" :mask="false" width="800px" :destroyOnClose="true">
        <slot></slot>
        <template #title>
    <div ref="modalTitleRef" style="width: 100%; cursor: move">{{ props.title }}</div>
        </template>
        <template #modalRender="{ originVNode }">
    <div :style="transformStyle" ref="modalRef">
        <component :is="originVNode" />
            </div>
        </template>
    </a-modal>
    

    其中modalTitleRef,被定义为可拖拽,modalRef用于响应拖拽变从而改变弹出框的位置。

  2. script

    <script setup lang="ts">
    import { storeToRefs } from "pinia";
    import { useMxGraphStore } from "@/stores/mxGraphStore.ts";
    import { useDraggable, useElementSize, useWindowSize } from "@vueuse/core";
    import { onMounted, ref, watch, watchEffect, computed, CSSProperties, onUpdated } from "vue";
    const props = defineProps<{ title: string }>();
    const mxGraphStore = useMxGraphStore();
    const { popoverInfo } = storeToRefs(mxGraphStore);  // 1. 会自动响应pinia中popoverInfo.visible的变化,从而控制打开
    const modalTitleRef = ref();
    const modalRef = ref();
    const { x, y, isDragging } = useDraggable(modalTitleRef); // 2.使用vueues 将头部做成可拖拽。
    const { width: widthM, height: heightM } = useElementSize(modalRef);
    const modalStyle = computed(() => `top: ${popoverInfo.value.position.y}px;left: ${popoverInfo.value.position.x}px;margin:0px`);
    const { width: widthW, height: heightW } = useWindowSize();
    const startX = ref<number>(0);
    const startY = ref<number>(0);
    const startedDrag = ref(false);
    const transformX = ref(0);
    const transformY = ref(0);
    const preTransformX = ref(0);
    const preTransformY = ref(0);
    const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 });
    watch([x, y], () => {
      if (!startedDrag.value) {
        startX.value = x.value;
        startY.value = y.value;
        const bodyRect = document.body.getBoundingClientRect();
        const titleRect = modalTitleRef.value.getBoundingClientRect();
        dragRect.value.right = bodyRect.width - titleRect.width;
        dragRect.value.bottom = bodyRect.height - titleRect.height;
        preTransformX.value = transformX.value;
        preTransformY.value = transformY.value;
      }
      startedDrag.value = true;
    });
    watch(isDragging, () => {
      if (!isDragging) {
        startedDrag.value = false;
      }
    });
    // 3.根据拖拽的坐标变化更新弹出框的位置(transformX)
    watchEffect(() => {
      if (startedDrag.value) {
        transformX.value = preTransformX.value + Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) - startX.value;
        transformY.value = preTransformY.value + Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) - startY.value;
      }
    });
    // 4.根据变化后的transformX真正更改弹出框位置
    const transformStyle = computed<CSSProperties>(() => {
      return {
        transform: `translate(${transformX.value}px, ${transformY.value}px)`,
      };
    });
    onMounted(() => {});
    </script>
    
### 如何在 Ant Design Vue 中使用对话框组件 #### 导入 Modal 组件 为了能够在项目中使用 `Modal` 对话框组件,需先导入该组件。这可以通过如下代码完成: ```javascript import { Modal } from 'ant-design-vue'; ``` 此操作确保了后续能够调用 `Modal` 提供的各种静态方法来显示不同类型的模态窗口[^1]。 #### 基本用法示例 下面是一个简单的例子,展示了如何创建并展示一个基础的信息提示框: ```html <template> <a-button @click="showConfirm">Show Confirm</a-button> </template> <script setup> const showConfirm = () => { Modal.confirm({ title: 'Do you Want to delete these items?', content: 'Some descriptions', okText: 'Yes', cancelText: 'No' }); }; </script> ``` 这段代码实现了点击按钮后弹出确认删除项目的对话框,其中包含了标题、描述文字以及两个按钮选项:“是”和“否”。这种形式非常适合用来获取用户的简单确认反馈。 #### 自定义对话框行为 除了标准的消息提示外,还可以进一步定制化对话框的行为逻辑。比如设置回调函数处理用户的选择动作;调整默认的按钮文本;甚至完全替换整个内容区域的内容等。具体来说就是利用 `onOk`, `onCancel` 参数传入相应的处理器函数,在这些函数内部编写业务逻辑即可满足特定应用场景下的需求。 #### 实现带拖拽功能的对话框 对于某些特殊情况下需要允许用户移动对话框位置的需求,则可以参考其他开发者分享的技术方案。一种可行的做法是在初始化时给定额外参数使能拖动特性,并监听鼠标事件以更新容器的位置坐标[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛_snail

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值