版本: ant-design-vue 1.6.2
效果(按住標題欄拖動,拖動超出窗口會自動出現滾動條):
組件文件結構:
index.vue
(需要注意的是footer和title的處理,其他的props都是一致的)

<template> <a-modal :class="[modalClass, simpleClass]" :visible="visible" v-bind="$props" :footer="null" :bodyStyle="{padding:0}" @ok="handleOk" @cancel="handleCancel"> <div class="ant-modal-body" :style="bodyStyle"> <slot></slot> </div> <div class="ant-modal-footer relative"> <slot name="footer"></slot> </div> <div v-if="!title && title !== ''" slot="title"> <slot name="title"></slot> </div> </a-modal> </template> <script> import props from './props.js' var mouseDownX = 0 var mouseDownY = 0 var deltaX = 0 var deltaY = 0 var sumX = 0 var sumY = 0 var header = null var contain = null var modalContent = null var onmousedown = false export default { name: 'DragModal', mixins: [props], props: { // 容器的類名 modalClass: { type: String, default: () => { return 'modal-box' } }, visible: { type: Boolean, default: () => { return false } }, title: { type: String, default: () => { return undefined } }, width: { type: String, default: () => { return '70%' } }, footer: { type: Boolean, default: () => { return true } } }, data () { return { } }, computed: { simpleClass () { return Math.random().toString(36).substring(2) } }, watch: { visible () { this.$nextTick(() => { this.initialEvent(this.visible) }) } }, mounted () { this.$nextTick(() => { this.initialEvent(this.visible) }) }, created () {}, beforeDestroy () { this.removeMove() window.removeEventListener('mouseup', this.removeUp, false) }, methods: { handleOk (e) { this.resetNum() this.$emit('ok', e) }, handleCancel (e) { this.resetNum() this.$emit('cancel', e) }, resetNum () { mouseDownX = 0 mouseDownY = 0 deltaX = 0 deltaY = 0 sumX = 0 sumY = 0 }, handleMove (event) { const delta1X = event.pageX - mouseDownX const delta1Y = event.pageY - mouseDownY deltaX = delta1X deltaY = delta1Y // console.log('delta1X:' + delta1X, 'sumX:' + sumX, 'delta1Y:' + delta1Y, 'sumY:' + sumY) modalContent.style.transform = `translate(${delta1X + sumX}px, ${delta1Y + sumY}px)` }, initialEvent (visible) { // console.log('--------- 初始化') // console.log('simpleClass===>', this.simpleClass) // console.log('document===>', document) if (visible) { setTimeout(() => { window.removeEventListener('mouseup', this.removeUp, false) contain = document.getElementsByClassName(this.simpleClass)[0] header = contain.getElementsByClassName('ant-modal-header')[0] modalContent = contain.getElementsByClassName('ant-modal-content')[0] modalContent.style.left = 0 modalContent.style.transform = 'translate(0px,0px)' // console.log('初始化-header:', header) // console.log('初始化-contain:', contain) // console.log('初始化-modalContent:', modalContent) header.style.cursor = 'all-scroll' // contain.onmousedown = (e) => { header.onmousedown = (e) => { onmousedown = true mouseDownX = e.pageX mouseDownY = e.pageY document.body.onselectstart = () => false window.addEventListener('mousemove', this.handleMove, false) } window.addEventListener('mouseup', this.removeUp, false) }, 0) } }, removeMove () { window.removeEventListener('mousemove', this.handleMove, false) }, removeUp (e) { // console.log('removeUp') document.body.onselectstart = () => true if (onmousedown && !(e.pageX === mouseDownX && e.pageY === mouseDownY)) { onmousedown = false sumX = sumX + deltaX sumY = sumY + deltaY // console.log('sumX:' + sumX, 'sumY:' + sumY) } this.removeMove() this.checkMove() } } } </script>
props.js
(直接把文檔的參數抄過來就行https://www.antdv.com/components/modal-cn/)

export default {
props: [
'afterClose', // Modal 完全關閉后的回調 function 無
'bodyStyle', // Modal body 樣式 object {}
'cancelText', // 取消按鈕文字 string| slot 取消
'centered', // 垂直居中展示 Modal Boolean false
'closable', // 是否顯示右上角的關閉按鈕 boolean true
'closeIcon', // 自定義關閉圖標 VNode | slot - 1.5.0
'confirmLoading', // 確定按鈕 loading boolean 無
'destroyOnClose', // 關閉時銷毀 Modal 里的子元素 boolean false
// 'footer', // 底部內容,當不需要默認底部按鈕時,可以設為 :footer="null" string|slot 確定取消按鈕
'forceRender', // 強制渲染 Modal boolean false
'getContainer', // 指定 Modal 掛載的 HTML 節點 (instance): HTMLElement () => document.body
'keyboard', // 是否支持鍵盤 esc 關閉 boolean true
'mask', // 是否展示遮罩 Boolean true
'maskClosable', // 點擊蒙層是否允許關閉 boolean true
'maskStyle', // 遮罩樣式 object {}
'okText', // 確認按鈕文字 string|slot 確定
'okType', // 確認按鈕類型 string primary
'okButtonProps', // ok 按鈕 props, 遵循 jsx規范 {props: ButtonProps, on: {}} -
'cancelButtonProps', // cancel 按鈕 props, 遵循 jsx規范 {props: ButtonProps, on: {}} -
'title', // 標題 string|slot 無
'visible', // (v-model) 對話框是否可見 boolean 無
'width', // 寬度 string|number 520
'wrapClassName', // 對話框外層容器的類名 string -
'zIndex', // 設置 Modal 的 z-index Number 1000
'dialogStyle', // 可用於設置浮層的樣式,調整浮層位置等 object - 1.6.1
'dialogClass' // 可用於設置浮層的類名 string
]
}
main.js中全局引入:

import DragModal from '@/components/DragModal'
Vue.component('DragModal', DragModal)
調用示范:
<!-- 圖片預覽彈窗 --> <drag-modal :visible="visible" @cancel="()=>visible=false"> 內容 </drag-modal>