首页 >> 大全

TS+Hooks二次封装antd Modal,实现可拖拽

2023-09-09 大全 23 作者:考证青年

文章目录 二、可拖动DIV三、封装 四、总结

一、最终效果

使用和React Hooks二次封装antd的Modal对话框,实现可拖拽效果,并且满足下面的小细节。最终效果图如下:

小细节: 拖动时鼠标于DIV的相对位置拖动时选中文字边界问题页面失去焦点销毁时回到原位

二、可拖动DIV

在实现Modal对话框拖拽的之前,可以在html页面上先实现一个可拖动的DIV,我是学习了这篇文章可拖动DIV。里面的具体原理细节可以参考这篇文章。

_js实现拖拽实现工作流_js实现拖拽效果

直接通过图的方式表达可能更加直观。主要就是要确定好相对移动距离和边界条件。我的在线测试DEMO

三、封装 1. 实现原理 有部分参考了这篇文章,antd Modal的class属性是ant-modal-,通过这个属性,获得Modal对话框具体左右视图边框的距离和,用于后续的定位。

相对移动位置

var cx = e.clientX - startPosX + styleLeft,cy = e.clientY - startPosY + styleTop;

Modal对话框位置再次点击更新

这里的132就是Modal高度的一半,为了让他销毁后每次都保持在视图中央。如果自己改变宽高度的话,可以再次封装style中的width,就不至于写死了。因为Modal组件关闭的时候,是不会自动销毁的,如果不写下面的代码,会导致再次点开Modal后,还是上次那个位置。这个地方写的不太好,继续优化。

    useEffect(() => {return () => {setStyleLT({styleLeft: 0,styleTop: window.innerHeight / 2 - 132})setFlag(true);}}, [props.isModalVisible])

2. 组件代码

import { Modal } from 'antd';
import { useState, useEffect } from 'react';interface ModalBoxxProps {title: string,isModalVisible: boolean,handleOk: any,handleCancel: any,children?: React.ReactNode,okText?: string,cancelText?: string
}
let content: HTMLDivElement, contentLeft: number = 0, contentRight: number = 0;const ModalBox: React.FC<ModalBoxxProps> = (props) => {const [styleLT, setStyleLT] = useState({styleLeft: 0, styleTop: window.innerHeight / 2 - 132});let [flag, setFlag] = useState<boolean>(true);const style = { left: styleLT.styleLeft, top: styleLT.styleTop }useEffect(() => {return () => {setStyleLT({styleLeft: 0,styleTop: window.innerHeight / 2 - 132})setFlag(true);}}, [props.isModalVisible])const onMouseDown = (e: any) => {e.preventDefault();if (flag) {content = document.getElementsByClassName("ant-modal-content")[0] as HTMLDivElement;contentLeft = content.getBoundingClientRect().left;contentRight = content.getBoundingClientRect().right - content.offsetWidth;setFlag(false);}// 记录初始移动的鼠标位置const startPosX = e.clientXconst startPosY = e.clientY;const { styleLeft, styleTop } = styleLT// 添加鼠标移动事件document.onmousemove = (e) => {var cx = e.clientX - startPosX + styleLeft,cy = e.clientY - startPosY + styleTop;if (cx < -contentLeft) {cx = -contentLeft;}if (cy < 0) {cy = 0;}if (cx > contentRight) {cx = contentRight;}if (window.innerHeight - cy < content.offsetHeight) {cy = window.innerHeight - content.offsetHeight;}setStyleLT({styleLeft: cx,styleTop: cy})} // 鼠标放开时去掉移动事件document.onmouseup = function (e) {document.onmousemove = nullif (e.clientX > window.innerWidth || e.clientY < 0 || e.clientX < 0 || e.clientY > window.innerHeight) {document.onmousemove = null}}}return (<Modaltitle={<divclassName='dragBoxBar'style={{ height: "100", width: "100%", cursor: 'move', userSelect: "none" }}onMouseDown={onMouseDown}>{props.title}</div>}visible={props.isModalVisible}onOk={props.handleOk}onCancel={props.handleCancel}style={style}wrapClassName='dragBox'okText={props.okText}cancelText={props.cancelText}>{props.children}</Modal>)
}export default ModalBox;

4. 组件调用

import { Button } from "antd";
import { useState } from "react";
// 引入组件
import { ModalBox } from "../Components";interface ListProps {name?: string,age?: number
}
const List = (props: ListProps) => {const [showModal, setShowModal] = useState<boolean>(false)const handleModal = () => {setShowModal(true);}const handleOk = () => {setShowModal(false);};const handleCancel = () => {setShowModal(false);};return (<><div>列表页组件</div><ModalBoxtitle="告警信息"isModalVisible={showModal}handleOk={handleOk}handleCancel={handleCancel}okText="确定"cancelText="取消"><p>告警</p><p>告警</p><p>告警</p></ModalBox><Button onClick={handleModal}>点击弹窗</Button></>)
}
export default List;

四、总结

Modal每次消失的时候,不太流畅,需要再次优化,如果有好的建议,希望能和我一起交流。(* ̄︶ ̄)

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了