vue之封装一个 弹窗组件 dialog

vue之封装一个 弹窗组件 dialog

在这里插入图片描述

  • 实现效果:
    • 点击按钮,弹窗显示出来
    • 点击关闭 || 取消 || 确定 弹窗隐藏
    • 弹出时候带着遮罩层以及过渡动画效果
    • 关闭时候,可以点击遮罩层关闭,
      • mashFlag熟悉控制是否点击遮罩层 是否触发关闭弹窗事件
<template>
  <!-- 遮罩层 self只是点击自己-->
  <transition name="dialog-fade">
    <div class="dialog_wrap" v-show="visible" @click.self="handleMaskClose">
      <div class="dialog" :style="{ width, marginTop: top }">
        <div class="dialog_header">
          <!-- 标题的具名插槽 不传值时候 直接取title 否者替换slot-->
          <slot name="title">
            <span class="dialog_header_title">{{ title }}</span>
          </slot>
          <button class="dialog_header_btn" @click="handleClose">
            <span class="removes" titl="关闭"></span>
          </button>
        </div>
        <div class="dialog_body">
          <slot>
            <span>这是一条消息</span>
          </slot>
        </div>
        <div class="dialog_footer">
          <slot name="footer"></slot>
          <slot name="footer">
            <button class="dialog_footer_cancel" @click="handleCancel">
              取消
            </button>
            <button class="dialog_footer_comfirm" @click="handleComfirm">
              确定
            </button>
          </slot>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
/**
 *
 * * 注意点::visible.sync="visible"
 * * * 就是原本使用 子组件修改父组件需要通过组件通讯,只不过子组件向父组件发射事件时候,
 * * * 可以设置一个限定的触发事件,也就是 `this.$emit("update:visible", false)`,
 * * * 这样的话,直接把 v-bind 与 @click 简化为 -> `:visible.sync="visible"` 可实现子组件修改父组件的状态
 */
export default {
  name: "Dialog",
  props: {
    title: {
      type: String,
      default: "消息",
    },
    width: {
      type: String,
      default: "50%",
    },
    top: {
      type: String,
      default: "15vh",
    },
    visible: {
      type: Boolean,
      default: false,
    },
    mashFlag: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {};
  },
  methods: {
    handleMaskClose() {
      if (!this.mashFlag) return false;
      this.$emit("update:visible", false);
    },
    handleClose() {
      this.$emit("update:visible", false);
    },
    handleCancel() {
      this.$emit("handleCancel");
    },
    handleComfirm() {
      this.$emit("handleComfirm");
    },
  },
  components: {},
};
</script>
<style  lang="scss" scoped>
.dialog-fade-enter-active {
  animation: fade 0.5s;
}
.dialog-fade-leave-active {
  animation: fade 0.5s reverse;
}

@keyframes fade {
  0% {
    opacity: 0;
    transform: translateY(-20px);
  }
  100% {
    opacity: 1;
    transform: translateY(0px);
  }
}
.dialog_wrap {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: auto;
  margin: 0;
  z-index: 2001;
  background: rgba(0, 0, 0, 0.5);
  .dialog {
    position: relative;
    margin: 15vh auto 50px;
    background: #fff;
    border-radius: 2px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    box-sizing: border-box;
    width: 30%;
    & > .dialog_header {
      padding: 20px 20px 10px;
      line-height: 24px;
      font-size: 18px;
      color: #303133;
      .dialog_header_btn {
        position: absolute;
        top: 20px;
        right: 20px;
        padding: 0;
        background: transparent;
        border: none;
        outline: none;
        cursor: pointer;
        font-size: 16px;
      }
      .removes {
        position: absolute;
        right: 0;
        top: 0;
        color: #303133;
        cursor: pointer;
      }
      .removes::before {
        content: "\2716";
      }
    }
    & > .dialog_body {
      padding: 30px 20px;
      color: #606266;
      font-size: 14px;
      word-break: break-all;
    }
    & > .dialog_footer {
      padding: 10px 20px 20px;
      text-align: right;
      box-sizing: border-box;
      button {
        background: transparent;
        padding: 4px 6px;
        border: none;
        outline: none;
        cursor: pointer;
        font-size: 14px;
        border: 1px solid #ccc;
      }
      .dialog_footer_cancel {
        margin-right: 20px;
      }
    }
  }
}
</style>

使用dialog组件 Home.vue

<template>
  <div class="home">
    <!-- <Dialog title="消息弹窗" width="60%" top="200px">
      <div slot="title">我是弹窗</div>
    </Dialog> -->
    <!-- @close="close" -->
    <Dialog :visible.sync="visible" @handleCancel="cancel" @handleComfirm="comfirm">
      <div>我是body</div>
      <!-- 若是替换底部按钮 使用以下方式 -->
      <!-- <div slot="footer">
        <button class="dialog_footer_cancel" @click="cancel">取消</button>
        <button class="dialog_footer_comfirm" @click="comfirm">确定</button>
      </div> -->
    </Dialog>
    <button @click="btnShow">点击显示</button>
    <!-- transition包裹一个元素后,这个元素的显示和隐藏就会自动添加一些类名 -->
    <transition name="dialog">
      <div v-show="visible">我是动画</div>
    </transition>
  </div>
</template>

<script>
import Dialog from "./Test/dialog/Dialog.vue";
export default {
  name: "Home",
  components: {
    Dialog,
  },
  data() {
    return {
      visible: false,
    };
  },
  methods: {
    btnShow() {
      this.visible = true;
    },
    cancel() {
      this.visible = false;
    },
    comfirm() {
      this.visible = false;
    },
  },
};
</script>
<style lang="scss" scoped>
.home {
  height: calc(100% - 34px);
  width: calc(100% - 34px);
  background: #fff;
  padding: 16px;
  border: 1px solid #ccc;
  /* button {
    background: transparent;
    padding: 4px 6px;
    border: none;
    outline: none;
    cursor: pointer;
    font-size: 14px;
    border: 1px solid #ccc;
  }
  .dialog_footer_cancel {
    margin-right: 20px;
  } */
}
</style>
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个基本的弹窗组件封装代码。代码中使用的是Element UI库中的Dialog组件,你可以根据自己的需求进行修改和定制。 ``` <template> <el-dialog :title="title" :visible.sync="visible" :modal="modal" :width="width" :fullscreen="fullscreen" :lock-scroll="lockScroll" :custom-class="customClass" :show-close="showClose" :before-close="beforeClose" > <slot></slot> </el-dialog> </template> <script> export default { name: 'MyDialog', props: { title: { // 弹窗标题 type: String, default: '' }, visible: { // 是否显示弹窗 type: Boolean, default: false }, modal: { // 是否为模态弹窗 type: Boolean, default: true }, width: { // 弹窗宽度 type: String, default: '50%' }, fullscreen: { // 是否全屏显示 type: Boolean, default: false }, lockScroll: { // 是否锁定滚动条 type: Boolean, default: true }, customClass: { // 自定义类名 type: String, default: '' }, showClose: { // 是否显示关闭按钮 type: Boolean, default: true }, beforeClose: { // 关闭前的回调函数 type: Function, default: () => {} } } } </script> ``` 这是一个非常基础的弹窗组件,你可以根据自己的需求进行扩展和修改。在使用时,你需要在父组件中引入该组件,并使用v-model绑定visible属性来控制弹窗的显示和隐藏状态。 ``` <template> <div> <el-button @click="visible = true">打开弹窗</el-button> <my-dialog v-model="visible" title="弹窗标题"> <p>这是弹窗内容</p> </my-dialog> </div> </template> <script> import MyDialog from './MyDialog.vue' export default { components: { MyDialog }, data() { return { visible: false } } } </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值