/**
fixed(固定定位) 这里所固定的参照对像是--可视窗口-而并非是body或是父级元素。可通过z-index进行层次分级。
*/
/**
fixed(固定定位) 这里所固定的参照对像是--可视窗口-而并非是body或是父级元素。可通过z-index进行层次分级。
*/
<template>
<!-- 外层蒙版 -->
<transition name="dialog" >
<!-- @mouseup.stop="clickUpDialog" -->
<div class="dialog-layer" :data-hash="timeStamp" v-if="show" @click="closeLayer" :style="{'z-index':computedZindex}" id="dialog-layer" >
<!-- 中间容器 -->
<div class="dialog-resize_wrapper" @click.stop="stopFn" :style="{'background-color':backgroundColor,'top':top,'left':left,transform:(left == '50%' && top == '50%') ? 'translate(-50%,-50%)' : (top !== '50%' ? 'translate(-50%,0)' : '')}">
<div class="dialog-wrapper" >
<!-- 容器的头部 -->
<div class="dialog-header" :style="{'font-size':computedHeaderFontSize,'color':headerColor}" @mousedown="clickDownDialog('mousedown')" @mousemove="moveDialog" @mouseup.stop="clickUpDialog('dialog-header-mouseup')" >
<!-- 标题的外层容器 -->
<div class="dialog-header_wrapper">
<div class="dialog-header_inner" >{{title}}</div>
<!-- 点击关闭的按钮外层容器 -->
<div class="dialog-close_wrapper" @click.stop="closeDialog" @mouseover="closeJudge(true)" @mouseout="closeJudge(false)">
<!-- 外层按钮 -->
<i class="dialog-header_close iconfont icon-shanchu" ></i>
</div>
</div>
</div>
<!-- 容器的内容,放置外部直接放置在容器里面的内容 为默认的插槽-->
<div class="dialog-content" ref="dialog-content" :style="{'width':computedWidth,'min-height':computedHeight,'min-width':minWidth,'max-width':maxWidth,'max-height':maxHeight,padding:contentPadding}" name="content" >
<!-- 写在组件里面的内容就插入到这里 -->
<slot ></slot>
</div>
<!-- 默认的按钮组,默认不显示,需要显示可以在引用组件的时候 :show-fotter="true"-->
<div class="dialog-footer" v-if="showFooter">
<button class="button" @click.stop="closeDialog">取消</button>
<button class="button primary" @click.stop="submit" :disabled="submitLoading">确定</button>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
// rebuild-dialog 这里这个名字不要更改,会影响组件的使用
name:'rebuild-dialog',
// 这里的 prop 只能增加不能减少
props:{
//弹窗的显示隐藏
show:{
default:false,
type:Boolean
},
zIndex:{
default:100,//默认层级
},
mofifyTop:{
//传入的top
default:null,
},
//弹窗的标题
title:{
default:'标题',
},
//传入的弹窗的宽
width:{
default:500,
},
//传入的弹窗的高
height:{
default:100,
type:Number
},
minWidth:{
default:500,
},
maxWidth:{
default:'95vw',
},
maxHeight:{
default:'85vh',
},
// 标题部分的背景色
headerBg:{
default:'white'
},
//标题部分的字体大小
headerFontSize:{
default:18,
},
//标题部分的字体颜色
headerColor:{
default:'rgb(60,60,60)'
},
// 容器内容的背景色
backgroundColor:{
default:'white'
},
contentPadding:{
default:'10px 18px 10px 10px'
},
//通过点击蒙版来关闭弹窗
clickModalCloseLayer:{
default:false,
},
//是否显示地步的按钮组
showFooter:{
default:false,
},
//点击确认之后的loading
submitLoading:{
default:false
},
//弹窗覆盖处理 --增加层级
appendToBody:{
default:false,
}
},
data () {
return {
showTest:false,//测试用
isDrag:false,//是否为拖拽,即长按并滑动鼠标
//定位 上
top:'50%',
left:'50%',
topTest:'20px',
leftTest:'20px',
//鼠标按下的时候鼠标所在的坐标
oldMouseX:'',
oldMouseY:'',
toClose:false,//是否有关闭意图
timeStamp:'',
}
},
computed:{
//计算后的容器宽度
computedWidth(){
console.log(this.width)
//传入可以是带px的字符串也可以是数值
if(typeof this.width == 'number'){
return this.width+'px'
}else{
return this.width
}
},
// 计算后的容器高度
computedHeight(){
if(typeof this.height == 'number'){
return this.height+'px'
}else{
return this.height
}
},
computedHeaderFontSize(){
if(typeof this.headerFontSize == 'number'){
return this.headerFontSize+'px'
}else{
return this.headerFontSize
}
},
//层级
computedZindex(){
let index = this.zIndex;
if(this.appendToBody){
//加深层级
index += 2;
}
return index
},
},
watch:{
// 当检测到这个值变化的时候,重置拖拽框的位置
show: {
immediate: true, // 将立即以表达式的当前值触发回调
handler (val) { // 固定写法
//初始值是0,操作后才是false
if(val === false){
//是关闭状态的时候才执行
this.reset();
}else if(val === true){
//执行一次append
this.reset(2);
this.$nextTick(()=>{
//有自定义的top传过来的时候
if(this.mofifyTop !== null){
this.top = this.mofifyTop;
}
})
}
},
// deep:true
}
},
mounted(){
//鼠标抬起事件应该做成监听
window.addEventListener('mouseup',this.clickUpDialog)
},
updated(){
if(this.$refs['dialog-content']){
this.$refs['dialog-content']
}
},
beforeDestroy(){
//销毁组件
window.removeEventListener('mouseup',this.clickUpDialog);
},
activated(){
console.log("哈哈哈哈");
},
methods:{
//阻止冒泡的函数,在允许点击蒙版关闭的时候需要用到,请勿删除
stopFn(){
},
//关闭弹窗
closeLayer(){
console.log("哈哈哈哈")
if(this.clickModalCloseLayer){
this.$emit('close')
}
},
submit(){
//点击确定
this.$emit('submit');
},
closeJudge(val){
//鼠标划过close的处理
this.toClose = val
},
//根据鼠标位置获取当前框的定位信息
getTarget(ev){
//有关闭意图的时候直接return
if(this.toClose){
return
}
// //可视区的高
let windowHeight = window.innerHeight;
// // 可视区的宽
let windowWidth = window.innerWidth;
ev = ev || window.event;
//计算具体的位置
if(this.isDrag){//拖拽的状态
if(ev.pageX + this.width/2 > windowWidth && ev.pageX > 0){
//超出宽度
this.left = windowWidth - this.width/2 + 20 ;
}else if(ev.pageX <= this.width/2){
this.left = this.width/2
}else{
this.left = (ev.pageX + 15)+'px';
}
if(ev.pageY + this.height+25 > windowHeight && ev.pageY > 0){
//超出高度
this.top = windowHeight - this.height - 25;
}else if(ev.pageY <= 0){
this.top = 0;
}else{
//加上运行的距离与按下时的坐标的比较
this.top = (ev.pageY )+'px';
}
}
},
clickDialog(ev){
//点击鼠标左键
if(ev.button == 0){
}
},
clickDownDialog(ev){
ev = ev || window.event;
//记录鼠标按下时候的坐标
this.oldMouseX = ev.pageX;
this.oldMouseY = ev.pageY;
//鼠标按下的事件
this.isDrag = true;
//开始获取坐标
// window.addEventListener('mousemove',this.getTarget);
},
clickUpDialog(val){
//鼠标松开事件
this.isDrag = false
//取消获取坐标
window.removeEventListener('mousemove',this.getTarget);
},
moveDialog(ev){
//按下左键之后才允许拖拽
if(this.isDrag){
window.addEventListener('mousemove',this.getTarget);//再添加监听
}
},
closeDialog(){
//需要关闭拖拽的动作,不然会干扰关闭弹窗
this.isDrag = false;
window.removeEventListener('mousemove',this.getTarget);
window.removeEventListener('mouseup',this.clickUpDialog);
this.reset();
this.$emit('close');
window.removeEventListener('mousemove',this.getTarget);
},
reset(times){
if(times){
this.oldMouseX = null;
this.oldMouseY = null;
console.log('other')
}
console.log("重置")
//重置弹框的位置
this.top = '50%';
this.left = '50%';
},
},
}
</script>
<style scoped lang="scss">
//一个简单的过渡 组件过渡
.dialog-enter-active,.list-leave-active{
transition:all 0.3s;
}
.dialog-enter,.list-leave-to{
height:0;
opacity: 0;
}
// 外层蒙版
.dialog-layer{
position:fixed;
top:0;
right:0;
bottom:0;
left:0;
background:rgba(0,0,0,0.5);
.dialog-resize_wrapper{
position:fixed;
background:white;
border-radius:4px;
}
.dialog-wrapper{
.dialog-header{
//禁止选中标题文字
user-select:none;
cursor:move;
color:#e8e8e8;
padding:5px 10px;
.dialog-header_wrapper{
width:100%;
display:flex;
justify-content: space-between;
align-items: center;
padding:4px 2px;
border-bottom:1px solid rgba(220,220,220,0.9);
.dialog-close_wrapper{
// border:1px solid red;
padding:0 3px;
.dialog-header_close{
//删除按钮
cursor: pointer;
font-size:24px;
color:rgba(130,130,130,0.9);
}
.dialog-header_close:hover{
color:#409eff;
}
}
}
}
.dialog-content{
// border:1px solid red;
overflow-y: auto;
box-sizing: border-box;
//设置最小的宽高
min-width:300px;
min-height:150px;
//传入胡内容太少,内容太靠上的处理
// display:flex;
// // justify-content: center;
// align-items: center;
// flex-wrap: wrap;
}
.dialog-footer{
border-top:1px solid #e8e8e8;
padding:6px 15px 6px 3px;
text-align:right;
}
}
}
//按钮样式
.button{
width:57px;
height:32px;
font-size:13px;
color:#333333;
outline: none;
border-radius:5px;
background:none;
margin-left:10px;
border:1px solid #e8e8e8;
}
.default{
background:white;
color:333333;
}
.default:hover{
background:rgba(255,255,255,0.8);
}
.primary{
background:rgb(39, 166, 240);
// box-shadow:0 0 2px 2px rgb(39, 162, 233);
color:white;
}
.primary:hover{
background:rgba(39, 166, 240,0.8);
}
.warning{
background:rgb(231, 112, 26);
// box-shadow:0 0 2px 2px rgb(231, 112, 26);
color:white;
}
.warning:hover{
background:rgb(231, 112, 26);
}
.danger{
background:rgb(179, 64, 69);
// box-shadow:0 0 2px 2px rgb(211, 99, 19);
color:white;
}
.danger:hover{
background:rgb(184, 73, 78);
}
</style>
基于vue的可拖拽组件
最新推荐文章于 2024-05-15 16:39:33 发布