赞
踩
通过自定义指令的方式封装的自定义弹出框如下(没有加遮罩):
- <template>
- <div class="popupBox" v-drags="draggable" v-if="visible">
- <div ref="dialogRef" class="ZHElelmessage_content dialog_content message_box" :class="className"
- :style="{ top: top, width: width, zIndex: zIndex + 'important' }">
- <div class="flex-box" style="justify-content: center; position: relative">
- <slot name="title_left"></slot>
- <div class="ZHElelmessage_header dialog_header" :style="{ padding: topPadding }">
- <slot name="header">
- <div>{{ title }}</div>
- </slot>
- </div>
- <slot name="title_right"></slot>
- </div>
-
- <div class="solt-content" :style="{
- padding: padding,
- }">
- <slot> </slot>
- </div>
- </div>
- </div>
- </template>
- <!-- 使用
- <ZHMessage
- :title='标题'
- :width="'550px'"
- :visible='开关'
- :top='15vh'
- @closeDialog='关闭开关'
- />
- -->
-
- <script setup>
- import {
- ref,
- reactive,
- getCurrentInstance,
- defineEmits,
- defineProps,
- onMounted,
- } from "vue";
- const dialogRef = ref();
- const emit = defineEmits(["closeDialog", "ChangeTop"]);
- const props = defineProps({
- title: {
- type: String,
- default: "标题",
- },
- width: {
- type: String || Number,
- default: "440px",
- },
- visible: {
- type: Boolean,
- default: false,
- },
- /**添加类名 */
- className: {
- type: String,
- default: "",
- },
- top: {
- type: String,
- default: "15vh",
- },
- /**图层z轴坐标 */
- zIndex: {
- type: String || Number,
- default: "9000",
- },
- draggable: {
- type: Boolean,
- default: true,
- },
- leftSide: {
- type: Number || String,
- default: "0px",
- },
- topSide: {
- type: [Number, String],
- default: "0px",
- },
- /**主内容内边距 */
- padding: {
- type: String,
- default: "20px 20px 20px",
- },
- /**头部内边距 */
- topPadding: {
- type: String,
- default: "10px 20px",
- },
- isPosition: {
- type: Boolean,
- default: false,
- },
- });
- const ChangeTop = (val) => {
- emit("ChangeTop", val);
- };
- const newTop = ref("");
- /**自定义拖动对话框指令(局部) */
- const vDrags = {
- mounted(el, binding) {
- // 自定义属性,判断是否可拖拽
- if (!binding.value) return;
- const dialogHeaderEl = el.querySelector(".dialog_header");
- const dragDom = el.querySelector(".dialog_content");
- dialogHeaderEl.style.cssText += ";cursor:move;";
- // dragDom.style.cssText += ';bottom:0px;'
-
- // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
- const sty = (function () {
- if (document.body.currentStyle) {
- // 在ie下兼容写法
- return (dom, attr) => dom.currentStyle[attr];
- }
- return (dom, attr) => getComputedStyle(dom, null)[attr];
- })();
-
- dialogHeaderEl.onmousedown = (e) => {
- // 鼠标按下,计算当前元素距离可视区的距离
- const disX = e.clientX - dialogHeaderEl.offsetLeft;
- const disY = e.clientY - dialogHeaderEl.offsetTop;
- const screenWidth = document.body.clientWidth; // body当前宽度
- const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取)
-
- const dragDomWidth = dragDom.offsetWidth; // 对话框宽度
- const dragDomheight = dragDom.offsetHeight; // 对话框高度
-
- const minDragDomLeft = dragDom.offsetLeft;
- const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
-
- const minDragDomTop = dragDom.offsetTop;
- const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
-
- // 获取到的值带px 正则匹配替换
- let styL = sty(dragDom, "left");
- // 为兼容ie
- if (styL === "auto") styL = "0px";
- let styT = sty(dragDom, "top");
-
- // console.log(styL)
- // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
- 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;
- }
-
- // 移动当前元素
- dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
-
- ChangeTop(top + styT);
- };
-
- document.onmouseup = function (e) {
- document.onmousemove = null;
- document.onmouseup = null;
- };
- return false;
- };
- },
- };
- onMounted(() => {
- if (props.isPosition) {
- dialogRef.value.style.setProperty("--ZHWidth", props.width);
- dialogRef.value.style.setProperty("--ZHTop", props.top);
- dialogRef.value.style.setProperty("--ZHLeftOffect", props.leftSide);
- dialogRef.value.style.setProperty("--ZHTopOffect", props.topSide);
- }
- });
- defineExpose({
- newTop,
- });
- /**提交回调事件 */
- const submitPopupData = () => { };
- </script>
-
- <style scoped lang="less">
- @dialogWidth: var(--ZHWidth, 330px);
- @dialogTop: var(--ZHTop, 15vh);
- @dialogLeftOffset: var(--ZHLeftOffect, 0px);
- @dialogTopOffset: var(--ZHTopOffect, 0px);
-
- .ZHElelmessage_header {
- width: 0;
- flex: 1;
- // padding: 10px 20px;
- background-color: #e9e9eb;
- border-radius: 5px 5px 0 0;
- // margin-bottom: 20px;
- font-size: 18px;
- }
-
- .ZHElelmessage_content {
- position: fixed;
- width: @dialogWidth;
- top: calc(@dialogTop + @dialogTopOffset);
- left: calc(50% - @dialogWidth / 2 + @dialogLeftOffset);
- box-shadow: 1px 5px 14px #a8abb2;
- z-index: 20000 !important;
- background-color: white;
- }
-
- .solt-content {
- font-size: 16px;
- }
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。