做一个可移动的弹窗(VUE)
2021-11-02 本文已影响0人
陈桑
前言:这里做一个可移动的弹窗,因为项目中使用到,且在写的时候发现很多坑。希望以后用到能够避免踩坑,特此记录。
示例:

可移动的弹窗组件:
<template>
<div class="dialogView">
<div class="dialogBox" ref="dialogEl" :style="{marginLeft:ml,marginTop:mt}">
<header class="dialogHeader" @mousedown="mouseDown">
<el-button @click="closeDialog">关闭</el-button>
</header>
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "moveDialog",
props: {},
data() {
return {
ml:'20%',
mt:'10%',
dialogB: false,
};
},
mouonted() {},
methods: {
closeDialog(){
this.ml='20%';
this.mt='10%';
return this.$emit('close')
},
mouseDown(e){
let windowH = window.innerHeight;//获取浏览器的可用高度
// let windowW = window.innerWidth;//获取浏览器的可用宽度
let el = this.$refs.dialogEl;//获取需要拖拽移动的容器
var disX = e.clientX - el.offsetLeft;
var disY = e.clientY - el.offsetTop;
this.dialogB = true;
document.onselectstart = function () {return false} // 使用js禁止用户选中网页上的内容(解决拖动会选中文字的问题,来源:https://blog.csdn.net/china_skag/article/details/41648647)
document.onmousemove = (e) => {
if (!this.dialogB) return false
let left = e.clientX - disX
let top = e.clientY - disY
if (top < 0 || top > windowH - 40) return false;//当到达顶部或者底部时就不让继续拖动了
this.ml = left + 'px'
this.mt = top + 'px'
}
document.onmouseup = () => {
if (!this.dialogB) return false
this.dialogB = false
}
},
},
};
</script>
<style scoped lang="scss">
.dialogView{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0,0,0,.5);
.dialogBox{
width: 60%;
height: 50%;
background-color: #ffffff;
.dialogHeader{
height: 40px;
cursor: all-scroll;
display: flex;
flex-direction: row-reverse;
box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
}
}
}
</style>
这里我没有使用弹性布局使弹窗组件进行居中,因为在设置后会和距离冲突。应该可以加一个动态的类,在鼠标摁下事件触发时把该类去除。
使用组件:
引入:
import moveDialog from '@/components/moveDialog.vue'// 引入组件
注册为局部组件:
components: {
moveDialog,//注册为局部组件
},
创建一个变量记录显示隐藏
data(){
return{
dialogShow:false,//创建一个记录弹窗显示隐藏的变量
}
},
在template内使用组件:
<div v-show = 'dialogShow'>
<!-- 接收组件发射出来的关闭事件 -->
<moveDialog @close = "closeDialog" >
<h3>这里面可以放任何的东西,所谓弹窗的内容。</h3>
</moveDialog>
</div>
关闭弹窗:
methods:{
// 关闭弹窗(子组件发射出来的自定义事件)
closeDialog(){
this.dialogShow = false;
},
},
代码都加了注释,很容易看懂。为了以后方便使用,特别记录。