Vue2 移动端(H5)项目封装弹窗组件

前言

vant-uidialog组件没有自定义footer插槽

效果

参数配置

1、代码示例:

html 复制代码
<t-dialog :visible.sync="show" :title="title" @submit="submit"></t-dialog>

2、配置参数(t-dialog Attributes)

参数 说明 类型 默认值
visible 是否显示弹窗 (必须加.sync 修饰符) Boolean false
title 弹窗标题 String '-
width 弹窗宽度 String 351px
height 弹窗高度 String auto
cancelButtonText 取消按钮文字 String 取消
confirmButtonText 确定按钮文字 String 确定
showCancelButton 是否显示取消按钮 Boolean true
showConfirmButton 是否显示确定按钮 Boolean true
isShowHeader 是否显示头部 Boolean true
isShowMask 是否显示遮罩层 Boolean true
isClickMaskClose 是否点击遮罩关闭弹窗 Boolean true
isCloseMask 是否显示标题右侧关闭icon Boolean true
footer 是否显示底部操作按钮(:footer="null") Object -

3、events 事件

事件名 说明 返回值
submit 点击确定按钮 -

4、slot 插槽

事件名 说明 返回值
title title插槽 -
- 默认内容区域插槽 -
footer 操作按钮插槽 -

三、源码

html 复制代码
<template>
  <div class="t_dialog" v-if="isShow">
    <div class="dialog_content" :style="{width: width, height: height}">
      <div class="header_title" v-if="isShowHeader">
        {{ title }}
        <slot name="title" />
        <van-icon @click="closePopup" v-if="isCloseMask" name="cross" />
      </div>
      <div class="content">
        <slot />
      </div>
      <div
        class="footer"
        :class="{'footer-no-button': !showCancelButton||!showConfirmButton, 'footer-null': (!showCancelButton&&!showConfirmButton)}"
        v-if="(footer!==null)"
      >
        <slot name="footer" />
        <template v-if="!$slots.footer">
          <van-button @click="closePopup" v-if="showCancelButton">{{cancelButtonText}}</van-button>
          <van-button type="danger" @click="submit" v-if="showConfirmButton">{{confirmButtonText}}</van-button>
        </template>
      </div>
    </div>
    <div class="dialog-mask" v-if="isShowMask" @click="closeMask"></div>
  </div>
</template>
<script>
export default {
  name: 'TDialog',
  props: {
    // 是否显示弹窗
    visible: {
      type: Boolean,
      default: false
    },
    // 弹窗标题
    title: {
      type: String,
    },
    width: {
      type: String,
      default: '351px'
    },
    height: {
      type: String,
      default: 'auto'
    },
    // 取消按钮文字
    cancelButtonText: {
      type: String,
      default: '取消'
    },
    // 确定按钮文字
    confirmButtonText: {
      type: String,
      default: '确定'
    },
    // 是否显示取消按钮
    showCancelButton: {
      type: Boolean,
      default: true
    },
    // 是否显示确定按钮
    showConfirmButton: {
      type: Boolean,
      default: true
    },
    // 是否显示头部
    isShowHeader: {
      type: Boolean,
      default: true
    },
    // 是否显示遮罩层
    isShowMask: {
      type: Boolean,
      default: true
    },
    // 是否点击遮罩关闭弹窗
    isClickMaskClose: {
      type: Boolean,
      default: true
    },
    // 是否显示关闭按钮
    isCloseMask: {
      type: Boolean,
      default: true
    },
    // 是否显示底部操作按钮 :footer="null"
    footer: Object,
  },
  computed: {
    isShow: {
      get() {
        return this.visible
      },
      set(val) {
        this.$emit('update:visible', val)
      }
    }
  },
  methods: {
    closePopup() {
      this.isShow = false
    },
    closeMask() {
      if (!this.isClickMaskClose) return
      this.isShow = false
    },
    submit() {
      this.$emit('submit')
      // this.isShow = false
    }
  },

}
</script>
<style lang="scss" scoped>
.t_dialog {
  .dialog_content {
    position: fixed;
    top: 50%;
    left: 50%;
    -webkit-transform: translate3d(-50%, -50%, 0);
    transform: translate3d(-50%, -50%, 0);
    max-width: 100%;
    max-height: 100%;
    background-color: #fff;
    z-index: 1000;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
  }
  .header_title {
    height: 40px;
    padding: 0 20px;
    font-size: 16px;
    color: #101010;
    background: #fff;
    border-bottom: 1px solid #e5e5e5;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    border-radius: 8px 8px 0 0;
    .van-icon {
      cursor: pointer;
      position: absolute;
      right: 20px;
      top: 50%;
      -webkit-transform: translateY(-50%);
      transform: translateY(-50%);
      font-size: 16px;
      color: #999;
      &:hover {
        color: #333;
      }
    }
  }
  .content {
    padding: 15px;
    width: calc(100% - 30px);
    overflow-y: auto;
  }
  .footer {
    height: 40px;
    line-height: 40px;
    color: #101010;
    background: #fff;
    border-top: 1px solid #e5e5e5;
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: relative;
    border-radius: 0 0 8px 8px;
    button {
      flex: 0 50%;
      height: 40px;
      line-height: 40px;
      padding: 0;
      font-size: 16px;
      border: none;
      border-radius: 0 0 8px 0px;
      &:first-child {
        border-right: 1px solid #e5e5e5;
        border-radius: 0 0 0px 8px;
      }
    }
    .van-button--primary {
      color: #007aff;
      border: none;
      background-color: #fff;
    }
    .van-button--danger {
      color: #ff4444;
      border: none;
      background-color: #fff;
    }
    &.footer-no-button {
      button {
        flex: 0 auto;
        border: none;
        border-radius: 0 0 8px 8px;
        width: 100%;
      }
    }
    &.footer-null {
      display: none;
    }
  }
  .dialog-mask {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #000;
    opacity: 0.7;
    z-index: 999;
  }
}
</style>

相关文章

基于ElementUi再次封装基础组件文档


基于ant-design-vue再次封装基础组件文档


vue3+ts基于Element-plus再次封装基础组件文档

相关推荐
空中海1 小时前
第七章:vue工程化与构建工具
前端·javascript·vue.js
旷世奇才李先生4 小时前
Vue3\+Vite\+Pinia实战:企业级后台管理系统完整实现(附源码)
vue.js
Cdlblbq9 小时前
搜索会员中心 创作中心Vue2项目一键打包成桌面应用
前端·javascript·vue.js·electron
A_nanda10 小时前
vue实现后端传输逐帧图像数据
前端·javascript·vue.js
当时只道寻常11 小时前
Vue3 集成 NProgress 进度条:从入门到精通
前端·vue.js
米丘11 小时前
Vue 3.x 单文件组件(SFC)模板编译过程解析
前端·vue.js·编译原理
米丘11 小时前
vue3.x 内置指令有哪些?
前端·vue.js
米丘11 小时前
Vue 3.x 模板编译优化:静态提升、预字符串化与 Block Tree
前端·vue.js·编译原理
空中海12 小时前
第一章:Vue 基础与模板语法
前端·javascript·vue.js
许彰午13 小时前
Spring Boot + Vue 实现 XML 动态表单:固定字段 + 自由扩展方案
xml·vue.js·spring boot