基于Ant Design的Modal组件来实现一个可拖拽的React模态框


  写这篇文章的原因是因为在项目中用到了Antd Design的React组件,当有业务需求需要用到模态框的时候遇到了一些小问题,Antd的模态框Modal组件时不能拖拽的,一般情况下不可拖拽也没什么大的问题,但是遇到了客户提的需求,因此就想着在Modal组件原有的基础上进行扩展,封装一个可拖拽的模态框,当然我使用的这种方式不一定是最好的,所以仅仅是用于参考。

  可以使用npm或yarn安装,可以直接使用下面的那段代码

  npm install dragm

  //OR

  yarn add dragm

  这是我安装之后直接复制了它的代码,你可以直接复制下面这段代码然后引入到自己项目中,而不需要在额外的安装

  //DragM.js

  import React from "react";

  import PropTypes from "prop-types";

  export default class DragM extends Reactponent {

  static propTypes={

  children: PropTypes.element.isRequired

  };

  static defaultProps={

  //默认是移动children dom,覆盖该方法,可以把tranform行为同步给外部

  updateTransform: (transformStr, tx, ty, tdom)=> {

  tdom.style.transform=transformStr;

  };

  position={

  startX: 0,

  startY: 0,

  dx: 0,

  dy: 0,

  tx: 0,

  ty: 0

  };

  start=event=> {

  if (event.button !==0) {

  //只允许左键,右键问题在于不选择conextmenu就不会触发mouseup事件

  return;

  document.addEventListener("mousemove", this.docMove);

  this.position.startX=event.pageX - this.position.dx;

  this.position.startY=event.pageY - this.position.dy;

  };

  docMove=event=> {

  const tx=event.pageX - this.position.startX;

  const ty=event.pageY - this.position.startY;

  const transformStr=`translate(${tx}px,${ty}px)`;

  thisps.updateTransform(transformStr, tx, ty, this.tdom);

  this.position.dx=tx;

  this.position.dy=ty;

  };

  docMouseUp=event=> {

  document.removeEventListener("mousemove", this.docMove);

  };

  componentDidMount() {

  this.tdom.addEventListener("mousedown", this.start);

  //用document移除对mousemove事件的监听

  document.addEventListener("mouseup", this.docMouseUp);

  componentWillUnmount() {

  this.tdom.removeEventListener("mousedown", this.start);

  document.removeEventListener("mouseup", this.docMouseUp);

  document.removeEventListener("mousemove", this.docMove);

  render() {

  const { children }=thisps;

  const newStyle={ ...childrenps.style, cursor: "move", userSelect: "none" };

  return React.cloneElement(React.Children.only(children), {

  ref: tdom=> {

  return (this.tdom=tdom);

  },

  style: newStyle

  });

  前提是你安装了Antd,同时记得修改DragM的路径

  //MovableModal.js

  import React, { Component } from "react";

  import { Modal } from "antd";

  import DragM from "./DragM";

  class MovableModal extends Component {

  render() {

  const updateTransform=transformStr=> {

  this.modalDom=document.getElementsByClassName("ant-modal-content")[0];

  this.modalDom.style.transform=transformStr;

  };

  const { children, title, ...other }=thisps;

  const mytitle=(

  );

  return (

  {thisps.children}

  );

  export default MovableModal;

  使用方式和Modal组件使用方式一样,没有增加则外的属性

  

  visible={visible}

  title="你的标题"

  onOk={this.handleOk}

  onCancel={this.handleCancel}

  footer={[

  

  key="submit"

  type="primary"

  loading={loading}

  onClick={this.handleOk}

  >

  提交

  >

  具体的相关事件需要自己处理,也就是控制模态框显隐等。

  这个方法目前发现的不足的地方就是在打开移动,然会关闭再打开就会发现位置保持在移动后的外置,因此需要在关闭后自己手动处理相关的属性。暂未发现明显的bug。

  本方法算是比较暴力的一个方法了,从结果来看基本满足客户需求,当然也有不足的地方,如果大家有更好的解决方案,欢迎到评论区留言。如果本文对你有帮助,请记得帮忙转发、点赞加关注哦!

相关