ant design vue a-modal實現拖拽彈窗
阿新 • • 發佈:2021-02-04
我tm終於成功了!!!大仇得報!文末有問題總結。
檔案目錄:
index.vue 檔案
<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">
<a-button @click="handleCancel" >取消</a-button>
<a-button type="primary" @click="handleOk">確定</a-button>
</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: Number,
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 檔案
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>
問題總結:
1. 原Po大神的程式碼是沒有底部按鈕的,需要自己按需新增。預設的確定和取消按鈕方法已經寫好了,只需要傳入事件,具體事件按需求重寫。
2. width屬性分為兩種,String|Number,預設為String型別,本程式需要使用Number。
最後再次要感謝原Po大神的程式碼!!