十五分钟两百行代码,手写一个vue项目全局通用的弹框

前言:

我们在写vue项目时,弹框是非常常用的组件,并且在同一个项目中,弹框大多类似。所以我们可以抽离封装出一个通用的弹框;

因为vue3可向下兼容,所以作者这边会使用vue2的写法,vue3写法大同小异。

第一步:新建相关文件

一般来说是在src/components/dialog下新建如下两个文件:

  1. index.vue:该文件是组件内容相关的,用来书写弹框组件的结构、样式、和动态逻辑;
  2. index.js:该文件使用虚拟节点创建组件内容,并且注册组件。

第二步:书写组件内容

index.vue组件内容如下:

  1. 结构 + js 代码
<template>
  <div class="default-message" :id="boxId">
    <div class="default-message-content">
      <div class="default-message-title">{{ title }}</div>
      <div class="default-message-value" v-html="message"></div>
      <div class="default-message-btns">
        <div
          class="default-message-cancle default-message-btn"
          v-if="cancelBtnHtml"
          @click.prevent.stop="handleCancel"
        >
          {{ cancelBtnHtml }}
        </div>
        <div
          class="default-message-submit default-message-btn"
          @click.prevent.stop="handleOk"
        >
          {{ okBtnHtml }}
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import i18n from "@/i18n";
import { defineComponent } from "vue";
export default defineComponent({
  name: "Dialog",
  data() {
    return {
      i18nTitle: '',
      i18nOkBtn: '',
    };
  },
  props: {
    boxId: {
      type: String,
      default: "",
    },
    // 标题
    title: {
      type: String,
      default: "",
    },
    // 内容
    message: {
      type: String,
      default: "",
    },
    // 确定按钮文字
    okBtnHtml: {
      type: String,
      default: '',
    },
    // 取消按钮文字
    cancelBtnHtml: {
      type: String,
      default: "",
    },
    // 成功回调
    ok_function: {
      type: Function,
    },
    // 失败回调
    cancel_function: {
      type: Function,
    },
  },
  methods: {
    handleCancel() {
      this.removeModal();
      this.cancel_function && this.cancel_function();
    },
    handleOk() {
      this.removeModal();
      this.ok_function && this.ok_function();
    },
    removeModal() {
      const modelDom = document.getElementById(
        "__default__container__content__"
      );
      if (modelDom) {
        document.body.removeChild(modelDom);
      }
    },
  },
  created() {
    this.i18nTitle = i18n.global.t('modal_warm_tip_title');
    this.i18nOkBtn = i18n.global.t('activity_ok');
  },
});
</script>

结构说明:

  • .default-message使我们整个弹框的容器,一般宽高都设置为100%,这个部分会有一个半透明的背景色(覆盖页面内容,防止弹框了还能操作页面);
  • .default-message-content为整个弹框的内容区域,包括标题、提示信息、取消按钮、确定按钮;
  • 取消按钮和确定按钮支持执行传入的事件,方便我们在弹框弹出后点击按钮执行相应操作;
  1. 样式
<style lang="less" scoped>
.default-message {
  position: fixed;
  right: 0;
  top: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.7);

  .default-message-title {
    color: #333;
    margin: 0;
    line-height: 1.5;
    font-size: 18px;
    min-height: 18px;
    padding-top: 20px;
    text-overflow: ellipsis;
    font-weight: bold;
    cursor: move;
    text-align: center;
  }

  .default-message-content {
    width: 85%;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate3d(-50%, -50%, 0);
    background-color: #fff;
    border-radius: 6px;
    transition: all 0.2s ease-in;
    color: #999;
    font-size: 18px;
  }

  .default-message-value {
    padding: 28px 18px;
    text-align: center;
    position: relative;
    color: #999;
    text-align: center;
    font-size: 14px;
    color: rgba(102, 102, 102, 1);
  }
  .default-message-btns {
    // border-top: 1px solid #ddd;
    display: flex;
    height: 60px;
    position: relative;
    &:after {
      position: absolute;
      content: "";
      display: inline-block;
      left: 0;
      right: 0;
      top: 0;
      height: 1px;
      transform: scaleY(0.5);
      background: #ddd;
    }
    .default-message-btn {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 16px;
      padding: 0 3px;
    }
    .default-message-submit {
      color: #26a2ff;
    }
    .default-message-cancle {
      color: #999;
      position: relative;
      &:after {
        position: absolute;
        content: "";
        display: inline-block;
        top: 0;
        right: 0;
        bottom: 0;
        width: 1px;
        transform: scaleX(0.5);
        background: #ddd;
      }
    }
  }
  @keyframes fadeIn {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
}
</style>

第三步:注册成全局组件

import {createVNode, render} from 'vue';
import MessageConstructor from './index.vue';

const $dialog = function (options) {
  // 已存在一个弹窗则不重复渲染
  if (!document.getElementById ('__default__container__content__')) {
    // 创建div
    const container = document.createElement ('div');
    // container.className = `__default__container__message__`;
    container.id = '__default__container__content__';
    //创建虚拟节点
    const vm = createVNode (MessageConstructor, options);
    //渲染虚拟节点
    render (vm, container);
    document.body.appendChild (container);
  }
};

export default {
  //组件注册
  install (app) {
    app.config.globalProperties.$dialog = $dialog;
  },
};

到这里,我们的弹框组件就完成了,接下来我们来使用看看。

项目中使用弹框

使用的方法也非常简单,所见即所得。

app.config.globalProperties.$dialog({
  title: "弹框标题",
  message: "弹框提示信息文案",
  okBtnHtml: "确定",
  cancelBtnHtml: "取消",
  ok_function: () => {
    console.log("点击弹框确定按钮处理函数");
  },
  cancel_function: () => {
    console.log("点击弹框取消按钮处理函数");
  }
});

说明:

  1. 标题、提示文案、以及取消和确定按钮文案,我们这边直接传入,ok_function是确定按钮的回调,我们可以在这里做任何点击确定后想做的事,包括发送请求和异步操作,cancel_function同理。
  2. 弹框图片示例:

在这里插入图片描述

写在后面

这是一个比较基础的弹框组件,这边示例的代码是比较全的,对细节要求不大的小伙伴可以直接用;

背景颜色、字体、布局等这些细节,因为每个业务场景不同,大家可以根据自己的需要适当调整;

弹框是固定单位的,如果小伙伴的项目需要使用响应式大小,直接对应替换大小单位即可;

对你有帮助的话给作者点点关注吧,你的支持是我不断更新的动力!Peace and love~~

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以通过以下步骤来自定义全局弹框: 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` 事件,并传递弹框的相关参数来显示全局弹框了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值