赞
踩
1、项目安装element-ui 并引入
npm i element-ui -S
//在main.js中引入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
2.封装element-ui的 Dialog 组件
在components中新建dialog.vue
<template>
<el-dialog v-el-drag-dialog :width="width" :modal-append-to-body="false" :close-on-click-modal="false" :before-close="handleClose" :visible.sync="visible">
<template slot="title">{{ title }}</template>
<template>
<component ref="page" :is="page" :param="param" @ok="onPageOk" @cancel="onPageCancel"></component>
</template>
<span slot="footer" class="dialog-footer" v-if="buttons && buttons.length > 0">
<el-button v-for="button of buttons" @click="buttonClicked(button)" :key="button.name" type="primary" style="margin-right: 10px">{{ button.name }}</el-button>
</span>
</el-dialog>
</template>
<script>
import elDragDialog from '@/directives/el-drag-dialog' // base on element-ui
export default {
name: 'DragDialogDemo',
directives: { elDragDialog },
data: function () {
return {
title: 'Title',
page: '',
width: '40%',
visible: true,
param: '',
buttons: [] // 每个元素是一个按钮,{ name: "确定", click: function() {} }, 从包含的page的buttons属性复制过来
}
},
methods: {
buttonClicked (button) {
button.click.bind(this.$refs.page).call() // 将按钮的事件绑定到page对象上
},
onPageOk (result) {
this.$emit('ok', result)
this.visible = false
},
onPageCancel () {
this.$emit('cancel')
this.visible = false
},
handleClose (done) {
this.$emit('cancel')
done()
}
}
}
</script>
<style lang="scss" scoped >
/deep/ .el-dialog {
border-radius: 5px;
transform: none;
left: 0;
position: relative;
margin: 0 auto;
display: flex;
flex-direction: column;
}
.el-dialog__header,
.el-dialog__body {
border-bottom: 1px solid gainsboro;
font-weight: 600;
font-size: 18px;
color: #409EFF;
max-height: 80vh !important;
overflow-y: auto;
}
</style>
2、封装打开Dialog方法
/** 加载页面 */
load(path) {
return new Promise((resolve, reject) => {
let name = names[path];
if (name != null) {
let page = pages[path];
resolve([name, page]);
return;
}
console.log(`加载页面: ${path}`);
import("@/pages/" + path + ".vue")
.then(module => {
let page = module.default;
name = "page" + sn++;
names[path] = name;
pages[path] = page;
Vue.component(name, page);
resolve([name, page]);
})
.catch(e => {
console.log(`加载页面失败: ${path}`);
reject(e);
});
});
},
/** 弹出页面 */
popup(title, path, param, width) {
return new Promise((resolve, reject) => {
load(path).then(([name, page]) => {
console.log(`弹出页面: ${title}: ${path}`);
// 准备对话框
let dialog = new Vue(Dialog);
dialog.title = title;
dialog.page = name;
dialog.param = param;
if (width == undefined || width == 'undefined ') {
dialog.width = '40%';
} else {
dialog.width = width + '%';
}
dialog.buttons = page.buttons; // 将page中的buttons复制到dialog中
dialog.$on("ok", (result) => {
resolve(result);
});
// 显示对话框
let div1 = document.createElement('div');
let div2 = document.createElement('div');
div1.appendChild(div2);
let body = document.getElementsByTagName('body')[0];
body.appendChild(div1);
dialog.$mount(div2);
dialog.$on("cancel", function () {
resolve();
});
dialog.$on("close", function () {
body.removeChild(div1);
});
});
});
},
3、封装拖拽自定义指令 ,在directives文件夹中新建el-drag-dialog文件夹,文件夹内新建drag.js 和index.js 以下是代码
drag.js
export default {
bind(el, binding, vnode) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cssText += ';cursor:move;'
dragDom.style.cssText += ';top:0px;'
const getStyle = (function() {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr]
} else {
return (dom, attr) => getComputedStyle(dom, false)[attr]
}
})()
dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
const dragDomWidth = dragDom.offsetWidth
const dragDomHeight = dragDom.offsetHeight
const screenWidth = document.body.clientWidth
const screenHeight = document.body.clientHeight
const minDragDomLeft = dragDom.offsetLeft
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
const minDragDomTop = dragDom.offsetTop
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
// 获取到的值带px 正则匹配替换
let styL = getStyle(dragDom, 'left')
let styT = getStyle(dragDom, 'top')
//
if (styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
} else {
styL = +styL.replace(/\px/g, '')
styT = +styT.replace(/\px/g, '')
}
document.onmousemove = function(e) {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX
let top = e.clientY - disY
// 边界处理
if (-(left) > minDragDomLeft) {
left = -minDragDomLeft
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft
}
if (-(top) > minDragDomTop) {
top = -minDragDomTop
} else if (top > maxDragDomTop) {
top = maxDragDomTop
}
// 移动当前元素
console.log( `;left:${left + styL}px;top:${top + styT}px;`)
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
vnode.child.$emit('dragDialog')
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
}
index.js
import drag from './drag'
const install = function(Vue) {
Vue.directive('el-drag-dialog', drag)
}
if (window.Vue) {
window['el-drag-dialog'] = drag
Vue.use(install); // eslint-disable-line
}
drag.install = install
export default drag
以上就是所有代码啦。通过popup方式打开Dialog后就可以在可视窗口内自由拖拽移动了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。