vue 实现一个简单的全局调用弹窗案例

时间:2021-10-06 04:01:10

1.实现效果图

vue 实现一个简单的全局调用弹窗案例

2.第一步,新建一个.vue文件 定义一个弹框的基本模板

style样式放在了文章的最底部,如果需要看效果,需要将样式放入这个vue文件里,样式是用less写的,需要你的项目引入less

注意:我这里的组件右上角关闭是一张图片 需要换成你自己本地的路径

  1. <template>
  2. <div id="tip_alertModal">
  3. <div class="t-alert-mask"></div>
  4. <div class="t-alert-container">
  5. <div class="t-alert-title">
  6. <span>
  7. {{title}}
  8. </span>
  9. <img @click="close" src="../../../static/images/alert/guanbi.png" alt="">
  10. </div>
  11. <div class="t-alert-content">
  12. <span class="content-text">
  13. {{content}}
  14. </span>
  15. </div>
  16. <div class="t-alert-confirm">
  17. <button @click="confirm">确定</button>
  18. <!-- 默认是没有取消按钮的,data定义默认true false -->
  19. <button class="cancel-btn" v-show="cancelBtn" @click="cancel">取消</button>
  20. </div>
  21. </div>
  22. </div>
  23. </template>
  24.  
  25. <script>
  26. export default {
  27. data() {
  28. return {
  29. show: true, // 通过这个属性,控制是否移除dom元素
  30. title:'', // 顶部标题
  31. content:'', // 内容
  32. cancelBtn: false // 取消按钮
  33. };
  34. },
  35. methods: {
  36. close() {
  37. // 右上角关闭
  38. this.a_close && this.a_close();
  39. this.show = false;
  40. // 删除判断增加的window属性
  41. delete window.alertIsShow;
  42. },
  43. confirm() {
  44. // 确定
  45. this.a_confirm && this.a_confirm();
  46. this.show = false;
  47. // 删除判断增加的window属性
  48. delete window.alertIsShow;
  49. },
  50. cancel() {
  51. // 取消
  52. this.a_cancel && this.a_cancel();
  53. this.show = false;
  54. // 删除判断增加的window属性
  55. delete window.alertIsShow;
  56. }
  57. },
  58. watch: {
  59. show(cur, old) {
  60. // 通过监控data里的show属性 弹框有三个事件(右上角取消 确定按钮 取消按钮)
  61. // 每个事件写了 this.show = false
  62. // 当弹框出现的时候 点击任何一个事件 都会触发这里的监控事件 将页面上的弹框Dom移除
  63. if (cur === false) {
  64. let tip_alert = document.getElementById('tip_alertModal');
  65. tip_alert.parentNode.removeChild(tip_alert);
  66. }
  67. }
  68. }
  69. }
  70. </script>

3.定义一个js文件

  1. import Vue from 'vue';
  2. import Alert from '@/components/public/alertModal'; //引入刚才写的弹框组件
  3. let AlertConstructor = Vue.extend(Alert); // 返回一个“扩展实例构造器”
  4.  
  5. let AlertModal = (o) => {
  6. let alertDom = new AlertConstructor({
  7. el: document.createElement('div'); //将Alert组件挂载到新创建的div上
  8. })
  9. document.body.appendChild(alertDom.$el); //把Alert组件的dom添加到body里
  10.  
  11. // 标题
  12. alertDom.title = o.title || '信息';
  13. // 单条内容
  14. alertDom.content = o.content;
  15. // 关闭按钮
  16. alertDom.cancelBtn = o.cancelBtn;
  17.  
  18. // 弹框三个事件 右上角关闭 确定 取消
  19. alertDom.a_close = o.close || null;
  20. alertDom.a_confirm = o.confirm || null;
  21. alertDom.a_cancel = o.cancel || null;
  22.  
  23. }
  24. export default AlertModal;

4.mian.js

import alert from '@/common/alertModal' //这里引入的是js文件

Vue.prototype.$alert = alert;

5.在任意组件调用

  1. <template>
  2. <div>
  3. <button @click="operate">点击调用弹框</button>
  4. </div>
  5. </template>
  6.  
  7. <script>
  8. export default {
  9. methods: {
  10. operate() {
  11. this.$alert({
  12. title: '信息',
  13. content: '登入成功!',
  14. cancelBtn: true, //这个是启用取消按钮,
  15. close() {
  16. // 这里执行点击右上角需要做的事,默认执行关闭弹框
  17. },
  18. confirm() {
  19. // 这里执行点击确定按钮需要做的事,默认执行关闭弹框
  20. },
  21. cancel() {
  22. // 这里执行点击取消按钮需要做的事,默认执行关闭弹框
  23. }
  24. })
  25. }
  26. }
  27. }
  28. </script>

取消按钮开启

vue 实现一个简单的全局调用弹窗案例

调用之后是往body添加元素

vue 实现一个简单的全局调用弹窗案例

5.通过window.alertIsShow,给window增加一个属性,来控制一个页面只会出现一个弹框

  1. methods: {
  2. operate () {
  3. if (!window.alertIsShow) {
  4. // 弹框模板有个 delete window.alertIsShow 是为了弹框关闭之后能再次显示
  5. this.$alert({
  6. title: '信息',
  7. content: '登入成功!',
  8. cancelBtn: true,
  9. close () {
  10. // 这里执行点击右上角需要做的事,默认执行关闭弹框
  11. },
  12. confirm () {
  13. // 这里执行点击确定按钮需要做的事,默认执行关闭弹框
  14. },
  15. cancel () {
  16. // 这里执行点击取消按钮需要做的事,默认执行关闭弹框
  17. }
  18. })
  19. window.alertIsShow = true;
  20. }
  21. }
  22. }

6.最后是弹框组件的less样式

  1. <style lang="less" scoped>
  2. #tip_alertModal {
  3. position: fixed;
  4. left: 0;
  5. top: 0;
  6. z-index: 100;
  7. width: 100%;
  8. height: 100%;
  9.  
  10. .t-alert-mask {
  11. position: absolute;
  12. top: 0;
  13. left: 0;
  14. width: 100%;
  15. height: 100%;
  16. background-color: rgba(0, 0, 0, .3);
  17. }
  18.  
  19. .t-alert-container {
  20. position: absolute;
  21. top: 50%;
  22. left: 50%;
  23. min-width: 240px;
  24. max-width: 400px;
  25. height: auto;
  26. background-color: #fff;
  27. transform: translate(-50%, -50%);
  28. border-radius: 4px;
  29.  
  30. .t-alert-title {
  31. position: relative;
  32. width: 100%;
  33. height: 40px;
  34. line-height: 40px;
  35. background-color: rgba(115, 134, 255, 1);
  36. border-radius: 4px 4px 0px 0px;
  37.  
  38. span {
  39. position: absolute;
  40. top: 50%;
  41. left: 10px;
  42. font-weight: 500;
  43. font-size: 16px;
  44. color: #fff;
  45. transform: translate(0, -50%);
  46. }
  47.  
  48. img {
  49. position: absolute;
  50. top: 50%;
  51. right: 10px;
  52. transform: translate(0, -50%);
  53. cursor: pointer;
  54. }
  55. }
  56.  
  57. .t-alert-content {
  58. text-align: center;
  59. span {
  60. font-family: PingFangSC-Regular;
  61. font-weight: 400;
  62. font-size: 14px;
  63. color: rgba(51,51,51,1);
  64. }
  65.  
  66. span.content-text {
  67. display: inline-block;
  68. width: 100%;
  69. height: auto;
  70. font-weight: 400;
  71. font-size: 14px;
  72. color: #333;
  73. padding: 20px 18px;
  74. }
  75. .t-content-list {
  76. min-width: 320px;
  77. height: auto;
  78. text-align: left;
  79. .list-title {
  80. position: relative;
  81. padding: 10px 0 10px 10px;
  82. img {
  83. display: inline-block;
  84. position: absolute;
  85. width: 20px;
  86. margin-right: 10px;
  87. }
  88. span {
  89. display: inline-block;
  90. vertical-align: middle;
  91. padding-left: 31px;
  92. }
  93. }
  94. .list-content {
  95. width: 100%;
  96. height: auto;
  97. ul {
  98. padding-bottom: 10px;
  99. li {
  100. width: 100%;
  101. height: auto;
  102. padding-bottom: 10px;
  103. span {
  104. vertical-align: top;
  105. }
  106. span.title {
  107. display: inline-block;
  108. padding-left: 41px;
  109. padding-right: 3px;
  110. text-align: left;
  111. }
  112. }
  113. }
  114. }
  115. }
  116. }
  117.  
  118. .t-alert-confirm {
  119. width: 100%;
  120. padding-bottom: 17px;
  121. text-align: center;
  122.  
  123. button {
  124. display: inline-block;
  125. width: 80px;
  126. height: 36px;
  127. border: none;
  128. background: rgba(115, 134, 255, 1);
  129. font-weight: 400;
  130. font-size: 16px;
  131. color: #fff;
  132. border-radius: 4px;
  133. outline: none;
  134. cursor: pointer;
  135. }
  136. .cancel-btn {
  137. margin-left:20px;
  138. background:rgba(151,193,234,1);
  139. font-family: PingFangSC-Regular;
  140. font-weight: 400;
  141. font-size: 16px;
  142. color: rgba(255,255,255,1);
  143. }
  144. }
  145. }
  146. }
  147. </style>

如果本篇文章对你有帮助的话,很高兴能够帮助上你。

补充知识:Vue注册全局组件-弹窗组件

在src目录下新建components文件夹

1.新建module文件夹,然后新建v-alert.vue

  1. <template>
  2. <transition name="fade">
  3. <div
  4. class="v-alert g-center"
  5. :style="{zIndex}">
  6. <div
  7. class="v-cont"
  8. :class="{shadow:!hideCont}"
  9. :style="[innerWidth]">
  10. <div
  11. v-if="title.trim()"
  12. :style="[{backgroundColor:bgColorTit,color:cancelCol},titleStyle]"
  13. class="title g-font18">
  14. {{title}}
  15. <span class="title-data">{{titleData}}</span>
  16. </div>
  17. <div
  18. v-if="isCancel"
  19. class="v-cancel">
  20. <div
  21. class="cancel-icon"
  22. :style="{color:cancelCol}"
  23. @click="cancel">
  24. </div>
  25. </div>
  26. <slot name="slot3"></slot>
  27. <div
  28. v-if="!hideCont"
  29. :style="styles"
  30. class="content">
  31. <slot></slot>
  32. </div>
  33. <slot name="slot2"></slot>
  34. </div>
  35. <div
  36. class="g-fixed alert-wrap"
  37. @click="$emit('cancel')"
  38. :style="{backgroundColor:bgWrapColor}"></div>
  39. </div>
  40. </transition>
  41. </template>
  1. <script>
  2. export default {
  3. name: "v-alert",
  4. props: {
  5. title: {default: ""},
  6. // titFontSize:{default: '16'},
  7. bgColorTit: {default: "#40404C"},
  8. bgColor: {default: "#fff"}, // 背景色
  9. bgWrapColor: {default: "rgba(42, 47, 59, 0.6)"}, //外套背景色
  10. cancelCol: {default: "#fff"}, //按钮颜色
  11. width: {required: true, type: Number}, //宽度
  12. minWidth: {type: Number, default: 0},
  13. isCancel: {type: Boolean, default: true}, //是否显示关闭按钮
  14. titleData: {default: ""},
  15. hideCont: {type: Boolean, default: false}, //是否隐藏cont
  16. zIndex: {default: 2000},
  17. styles: {
  18. default() {
  19. return {};
  20. },
  21. type: Object
  22. },
  23. titleStyle: {
  24. default() {
  25. return {};
  26. },
  27. type: Object
  28. },
  29. },
  30. components: {},
  31. computed: {
  32. innerWidth() {
  33. let dfu = {
  34. backgroundColor: this.bgColor
  35. };
  36. this.minWidth > 0
  37. ? dfu.minWidth = `${this.minWidth}px`
  38. : dfu.width = `${this.width}px`;
  39. return dfu;
  40. }
  41. },
  42. methods: {
  43. cancel() {
  44. this.$emit("cancel");
  45. }
  46. },
  47. mounted() {
  48. document.addEventListener(
  49. "keydown",
  50. event => {
  51. let keyCode = this.$_lib.getKeycode(event);
  52. if (keyCode === 'Escape' || keyCode === 27) this.$emit("cancel");
  53. },
  54. false
  55. );
  56. }
  57. };
  58. </script>
  1. <style lang="scss"
  2. rel="stylesheet/scss"
  3. scoped>
  4. .v-alert {
  5. position: fixed;
  6. top: 0;
  7. left: 0;
  8. width: 100%;
  9. height: 100%;
  10. z-index: 2000;
  11. .alert-wrap {
  12. top: 0;
  13. left: 0;
  14. width: 100%;
  15. height: 100%;
  16. /*z-index: 2000;*/
  17. }
  18. .v-cont {
  19. min-width: 100px;
  20. min-height: 100px;
  21. background-color: #ffffff;
  22. position: relative;
  23. border-radius: 2px;
  24. .shadow {
  25. box-shadow: 0 2px 30px rgba(42, 47, 59, 0.2);
  26. }
  27. z-index: 2001;
  28. .title {
  29. width: 100%;
  30. line-height: 70px;
  31. color: #ffffff;
  32. padding-left: 30px;
  33. }
  34. .title-data {
  35. color: #f8e19a;
  36. }
  37. .content {
  38. padding: 40px;
  39. /*padding: 60px 40px 50px 40px;*/
  40. word-wrap: break-word;
  41. text-align: left;
  42. }
  43. }
  44.  
  45. .v-cancel {
  46. position: absolute;
  47. top: 0;
  48. right: 0;
  49. width: 100%;
  50. height: 70px;
  51. }
  52. .cancel-icon {
  53. position: absolute;
  54. text-align: center;
  55. width: 20px;
  56. height: 20px;
  57. line-height: 20px;
  58. right: 20px;
  59. top: 50%;
  60. margin-top: -10px;
  61. color: #ffffff;
  62. cursor: pointer;
  63. transition: 200ms;
  64. &:hover {
  65. -webkit-transform: rotate(90deg);
  66. -moz-transform: rotate(90deg);
  67. -ms-transform: rotate(90deg);
  68. -o-transform: rotate(90deg);
  69. transform: rotate(90deg);
  70. }
  71. }
  72. }
  73. </style>

2.在nodule同级目录新建vue-component.js

  1. import VAlert from './v-alert'; //弹窗
  2.  
  3. export default {
  4. install(Vue) {
  5. Vue.component('VAlert', VAlert);
  6. }
  7. };

3.在main.js中注册为全局组件

import vueComponent from "./components/vue-component";

Vue.use(vueComponent);

4.在其他组件可以直接用了,无需import

  1. <template>
  2. <v-alert
  3. v-if="is_alert"
  4. @cancel="is_alert=false"
  5. bg-color-tit="#40404C"
  6. cancel-col="#fff"
  7. :title="提示"
  8. :width="680">
  9. <div></div>
  10. </v-alert>
  11. </template>

以上这篇vue 实现一个简单的全局调用弹窗案例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。