寫這篇文章的原因是因為在項目中用到了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組件使用方式一樣,沒有增加則外的屬性
<MovableModal
visible={visible}
title="你的標題"
onOk={this.handleOk}
onCancel={this.handleCancel}
footer={[
,
<Button
key="submit"
type="primary"
loading={loading}
onClick={this.handleOk}
>
提交
>
具體的相關事件需要自己處理,也就是控制模態框顯隱等。
這個方法目前發現的不足的地方就是在打開移動,然會關閉再打開就會發現位置保持在移動后的外置,因此需要在關閉后自己手動處理相關的屬性。暫未發現明顯的bug。
本方法算是比較暴力的一個方法了,從結果來看基本滿足客戶需求,當然也有不足的地方,如果大家有更好的解決方案,歡迎到評論區留言。如果本文對你有幫助,請記得幫忙轉發、點贊加關注哦!