当前位置:   article > 正文

vue3自定义对话框组件实现_vue3的聊天发送框组件

vue3的聊天发送框组件

通过自定义指令的方式封装的自定义弹出框如下(没有加遮罩):

  1. <template>
  2. <div class="popupBox" v-drags="draggable" v-if="visible">
  3. <div ref="dialogRef" class="ZHElelmessage_content dialog_content message_box" :class="className"
  4. :style="{ top: top, width: width, zIndex: zIndex + 'important' }">
  5. <div class="flex-box" style="justify-content: center; position: relative">
  6. <slot name="title_left"></slot>
  7. <div class="ZHElelmessage_header dialog_header" :style="{ padding: topPadding }">
  8. <slot name="header">
  9. <div>{{ title }}</div>
  10. </slot>
  11. </div>
  12. <slot name="title_right"></slot>
  13. </div>
  14. <div class="solt-content" :style="{
  15. padding: padding,
  16. }">
  17. <slot> </slot>
  18. </div>
  19. </div>
  20. </div>
  21. </template>
  22. <!-- 使用
  23. <ZHMessage
  24. :title='标题'
  25. :width="'550px'"
  26. :visible='开关'
  27. :top='15vh'
  28. @closeDialog='关闭开关'
  29. />
  30. -->
  31. <script setup>
  32. import {
  33. ref,
  34. reactive,
  35. getCurrentInstance,
  36. defineEmits,
  37. defineProps,
  38. onMounted,
  39. } from "vue";
  40. const dialogRef = ref();
  41. const emit = defineEmits(["closeDialog", "ChangeTop"]);
  42. const props = defineProps({
  43. title: {
  44. type: String,
  45. default: "标题",
  46. },
  47. width: {
  48. type: String || Number,
  49. default: "440px",
  50. },
  51. visible: {
  52. type: Boolean,
  53. default: false,
  54. },
  55. /**添加类名 */
  56. className: {
  57. type: String,
  58. default: "",
  59. },
  60. top: {
  61. type: String,
  62. default: "15vh",
  63. },
  64. /**图层z轴坐标 */
  65. zIndex: {
  66. type: String || Number,
  67. default: "9000",
  68. },
  69. draggable: {
  70. type: Boolean,
  71. default: true,
  72. },
  73. leftSide: {
  74. type: Number || String,
  75. default: "0px",
  76. },
  77. topSide: {
  78. type: [Number, String],
  79. default: "0px",
  80. },
  81. /**主内容内边距 */
  82. padding: {
  83. type: String,
  84. default: "20px 20px 20px",
  85. },
  86. /**头部内边距 */
  87. topPadding: {
  88. type: String,
  89. default: "10px 20px",
  90. },
  91. isPosition: {
  92. type: Boolean,
  93. default: false,
  94. },
  95. });
  96. const ChangeTop = (val) => {
  97. emit("ChangeTop", val);
  98. };
  99. const newTop = ref("");
  100. /**自定义拖动对话框指令(局部) */
  101. const vDrags = {
  102. mounted(el, binding) {
  103. // 自定义属性,判断是否可拖拽
  104. if (!binding.value) return;
  105. const dialogHeaderEl = el.querySelector(".dialog_header");
  106. const dragDom = el.querySelector(".dialog_content");
  107. dialogHeaderEl.style.cssText += ";cursor:move;";
  108. // dragDom.style.cssText += ';bottom:0px;'
  109. // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
  110. const sty = (function () {
  111. if (document.body.currentStyle) {
  112. // 在ie下兼容写法
  113. return (dom, attr) => dom.currentStyle[attr];
  114. }
  115. return (dom, attr) => getComputedStyle(dom, null)[attr];
  116. })();
  117. dialogHeaderEl.onmousedown = (e) => {
  118. // 鼠标按下,计算当前元素距离可视区的距离
  119. const disX = e.clientX - dialogHeaderEl.offsetLeft;
  120. const disY = e.clientY - dialogHeaderEl.offsetTop;
  121. const screenWidth = document.body.clientWidth; // body当前宽度
  122. const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取)
  123. const dragDomWidth = dragDom.offsetWidth; // 对话框宽度
  124. const dragDomheight = dragDom.offsetHeight; // 对话框高度
  125. const minDragDomLeft = dragDom.offsetLeft;
  126. const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
  127. const minDragDomTop = dragDom.offsetTop;
  128. const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
  129. // 获取到的值带px 正则匹配替换
  130. let styL = sty(dragDom, "left");
  131. // 为兼容ie
  132. if (styL === "auto") styL = "0px";
  133. let styT = sty(dragDom, "top");
  134. // console.log(styL)
  135. // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
  136. if (styL.includes("%")) {
  137. styL = +document.body.clientWidth * (+styL.replace(/%/g, "") / 100);
  138. styT = +document.body.clientHeight * (+styT.replace(/%/g, "") / 100);
  139. } else {
  140. styL = +styL.replace(/px/g, "");
  141. styT = +styT.replace(/px/g, "");
  142. }
  143. document.onmousemove = function (e) {
  144. // 通过事件委托,计算移动的距离
  145. let left = e.clientX - disX;
  146. let top = e.clientY - disY;
  147. // 边界处理
  148. if (-left > minDragDomLeft) {
  149. left = -minDragDomLeft;
  150. } else if (left > maxDragDomLeft) {
  151. left = maxDragDomLeft;
  152. }
  153. if (-top > minDragDomTop) {
  154. top = -minDragDomTop;
  155. } else if (top > maxDragDomTop) {
  156. top = maxDragDomTop;
  157. }
  158. // 移动当前元素
  159. dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
  160. ChangeTop(top + styT);
  161. };
  162. document.onmouseup = function (e) {
  163. document.onmousemove = null;
  164. document.onmouseup = null;
  165. };
  166. return false;
  167. };
  168. },
  169. };
  170. onMounted(() => {
  171. if (props.isPosition) {
  172. dialogRef.value.style.setProperty("--ZHWidth", props.width);
  173. dialogRef.value.style.setProperty("--ZHTop", props.top);
  174. dialogRef.value.style.setProperty("--ZHLeftOffect", props.leftSide);
  175. dialogRef.value.style.setProperty("--ZHTopOffect", props.topSide);
  176. }
  177. });
  178. defineExpose({
  179. newTop,
  180. });
  181. /**提交回调事件 */
  182. const submitPopupData = () => { };
  183. </script>
  184. <style scoped lang="less">
  185. @dialogWidth: var(--ZHWidth, 330px);
  186. @dialogTop: var(--ZHTop, 15vh);
  187. @dialogLeftOffset: var(--ZHLeftOffect, 0px);
  188. @dialogTopOffset: var(--ZHTopOffect, 0px);
  189. .ZHElelmessage_header {
  190. width: 0;
  191. flex: 1;
  192. // padding: 10px 20px;
  193. background-color: #e9e9eb;
  194. border-radius: 5px 5px 0 0;
  195. // margin-bottom: 20px;
  196. font-size: 18px;
  197. }
  198. .ZHElelmessage_content {
  199. position: fixed;
  200. width: @dialogWidth;
  201. top: calc(@dialogTop + @dialogTopOffset);
  202. left: calc(50% - @dialogWidth / 2 + @dialogLeftOffset);
  203. box-shadow: 1px 5px 14px #a8abb2;
  204. z-index: 20000 !important;
  205. background-color: white;
  206. }
  207. .solt-content {
  208. font-size: 16px;
  209. }
  210. </style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/355530?site
推荐阅读
相关标签
  

闽ICP备14008679号