Vue 自定义一个全局弹框组件

本文详细介绍了如何在Vue项目中创建一个自定义的全局弹框组件,以满足UI设计需求,包括组件样式、方法实现和Vue原型上添加$popupMessage方法。通过实例代码和效果图展示了如何在页面中调用该组件及其参数传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前文:其实element ui有提供this.$mesage和this.$notify弹框组件可供使用,但是我们的ui设计的样式以及布局还是不完全一样的,为了达到100%的呈现效果,所以自己写了一个全局组件,然后在页面上直接this.$popupMessage()调用

首先,需要创建一个vue文件来写我们的弹框样式,新建PopupMessage.vue

<template>
  <div class="popup-message warning">
    <div class="pop-view">
      <span class="pop-title">标头</span>
      <p class="pop-content">内容</p>
      <div class="pop-btn">
        <el-button type="primary" class="save" @click="closeMessage">确定</el-button>
      </div>
      <i class="delete" @click="closeMessage"></i>
    </div>
    
  </div>
</template>

methods: {

    getParams(options) {

              this.callBack = options.callBack;

               // options就是调用this.$popupMessage传过来的参数和方法

     }

}

需要我们在main.js里面给Vue添加$popupMessage方法,使用$mount()给组件手动挂载参数,然后将组件插入页面中

提示:$mount()里面如果没有参数,说明组件只是渲染了但是还没挂载到页面

import PopupMessage from "@/components/PopupMessage.vue" // 将组件引入

let popupMessage = null

let init = () => {

        // 用Vue.extend 创建组件的模板(构造函数)

        let messageConstructor = Vue.extend(PopupMessage);

        // 实例化组件,构造函数可以传参 data, method

        popupMessage = new messageConstructor({});

        // 挂载组件到页面上

        popupMessage.$mount();

        document.body.appendChild(popupMessage.$el)

}

let caller = (options) => {

        init(options);

        // getParams是在组件里定义的方法,获取传过来的参数和方法

        popupMessage.getParams(options);

}

Vue.prototype.$popupMessage = caller;

然后我们就可以在想要调用的地方直接使用this.$popupMessage()用啦

以下是我实际项目的代码和运行结果效果图,有需要的可以参考

popupMessage.vue

<template>
  <div class="popup-message warning" :class="type">
    <div class="pop-view">
      <span class="pop-title">{{ this.tips || ''}}</span>
      <p class="pop-content" v-if="this.msg">{{ this.msg }}</p>
      <div class="pop-btn" v-if="button">
        <el-button type="primary" class="save" @click="closeMessage">确定</el-button>
      </div>
      <i class="delete" @click="closeMessage"></i>
    </div>
    
  </div>
</template>

<script>

export default {
  name: 'PopupMessage',
  // props: ["timeVisible", "cfgData", "timeTitle"],
  data() {
    return {
      // 
      callback: null,
      tips: '',
      type: '',
      msg: '',
      button: false,
      duration: 0,
    };
  },
  computed: {
    //
  },
  methods: {
    getParams(options) {
      this.callBack = options.callBack;
      this.type = options.type || ''
      this.tips = options.tips || ''
      this.msg = options.msg || ''
      this.button = options.button || false
      this.duration = options.duration || 0

      this.changePosition()
      if(this.duration > 0){
        window.setTimeout(() => {

          this.$destroy(true)
          if(this.$el.parentNode){ // 当前节点是否已经被手动移除
            this.$el.parentNode.removeChild(this.$el)
          }

          this.changePosition()
        }, this.duration)
      }
    },
    changePosition() {
      let doc = document.body.getElementsByClassName('popup-message')
      let sum = 0;
      for(let i=0; i< doc.length; i++){
        this.$nextTick(() => {
          if(i>0){
            sum = sum + document.body.getElementsByClassName('popup-message')[i-1].clientHeight + 5
            document.body.getElementsByClassName('popup-message')[i].style = `top: ${sum}px`
          }else{
            document.body.getElementsByClassName('popup-message')[i].style = `top: 0`
          }
        })
         
      }
    },
    closeMessage(){
      this.$destroy(true)
      this.$el.parentNode.removeChild(this.$el)
      this.changePosition()
    }
    
  },
  mounted() {
  },
};
</script>
<style lang="scss" scoped>

.popup-message {
  font-family: "Source Han Sans Regular";
  color: #333333;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 500px;
  height: fit-content;
  border-radius: 8px;
  background: #FFFFFF;
  border: 1px solid #C2C2C2;
  z-index: 9999;
  .pop-view{
    position: relative;
    min-height: 120px;
    height: auto;
    padding-bottom: 13px;
    .pop-title{
      display: block;
      font-size: 18px;
      font-weight: 500;
      padding: 13px 52px 9px 52px;
      position: relative;
      &::before{
        position: absolute;
        content: '';
        background-image: url('~@/assets/popup/warning.png');
        width: 22px;
        height: 22px;
        left: 20px;
      }
    }
    .pop-content{
      font-weight: 400;
      font-size: 14px;
      padding: 0 52px 5px 52px;
    }
    .pop-btn{
      display: flex;
      justify-content: flex-end;
      .save{
        margin-right: 20px;
      }
    }
    .delete{
      position: absolute;
      content: '';
      background-image: url('~@/assets/popup/delete.png');
      width: 22px;
      height: 22px;
      top: 18px;
      right: 23px;
    }
  }
}
.success{
  background: #F6FFED;
  border: 1px solid #73D13D;
  color: #73D13D;
  .pop-view{
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%;
  }
  
  .pop-view>.pop-title{
    &::before{
      background-image: url('~@/assets/popup/success.png');
    }
  }
}
.error{
  background: #FFF1F0;
  border: 1px solid #FF7875;
  // color: #FF7875;
  .pop-view>.pop-title{
    &::before{
      background-image: url('~@/assets/popup/error.png');
    }
  }
}
</style>

main.js

import PopupMessage from '@/components/PopupMessage.vue';
let popupMessage = null;
let init = () => {
  let messageConstructor = Vue.extend(PopupMessage);
  // 构造函数可以传参,data,method
  popupMessage = new messageConstructor({});
  popupMessage.$mount();
  document.body.appendChild(popupMessage.$el);
}
let caller = (options) => {
  init(options);
  // PopupMessage.vue 中使用getParams接收调用时传入的参数。 type: image等
  popupMessage.getParams(options);
}

页面使用

this.$popupMessage({
    tips: "title", // 标题
    msg: 'content', // 内容
    type: 'type', // 弹框类型
    button: true, // 确定按钮
    duration: 3000, // 延迟时间
    callBack: (data) => {
       // ...
    }
})

效果图

 

你可以通过以下步骤来自定义全局: 1. 在项目中新建一个全局组件,例如 `GlobalDialog.vue`。 2. 在 `main.js` 中导入该组件并注册为全局组件: ```javascript import GlobalDialog from '@/components/GlobalDialog.vue' Vue.component('global-dialog', GlobalDialog) ``` 3. 在需要使用组件中,使用 `$emit` 方法触发一个事件,例如 `open-dialog`: ```javascript // 在组件中 this.$emit('open-dialog', { title: '标题', content: '内容', confirmText: '确认按钮文字', cancelText: '取消按钮文字', onConfirm: () => { // 确认按钮回调 }, onCancel: () => { // 取消按钮回调 } }) ``` 4. 在 `App.vue` 中监听该事件并显示全局: ```html <template> <div id="app"> <global-dialog v-if="dialogVisible" :title="dialogTitle" :content="dialogContent" :confirm-text="confirmText" :cancel-text="cancelText" @confirm="dialogOnConfirm" @cancel="dialogOnCancel" ></global-dialog> <router-view @open-dialog="showDialog"></router-view> </div> </template> <script> export default { name: 'App', data() { return { dialogVisible: false, dialogTitle: '', dialogContent: '', confirmText: '', cancelText: '', dialogOnConfirm: () => {}, dialogOnCancel: () => {} } }, methods: { showDialog(data) { this.dialogTitle = data.title this.dialogContent = data.content this.confirmText = data.confirmText || '确定' this.cancelText = data.cancelText || '取消' this.dialogOnConfirm = data.onConfirm || (() => {}) this.dialogOnCancel = data.onCancel || (() => {}) this.dialogVisible = true } } } </script> ``` 这样就可以在任何需要使用全局组件中,通过 `$emit` 方法触发 `open-dialog` 事件,并传递的相关参数来显示全局了。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值