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再次封装基础组件文档

相关推荐
前端小趴菜057 小时前
React - createPortal
前端·vue.js·react.js
三原10 小时前
7000块帮朋友做了2个小程序加一个后台管理系统,值不值?
前端·vue.js·微信小程序
白仑色10 小时前
完整 Spring Boot + Vue 登录系统
vue.js·spring boot·后端
阳火锅11 小时前
Vue 开发者的外挂工具:配置一个 JSON,自动造出一整套页面!
javascript·vue.js·面试
G_whang12 小时前
jenkins部署前端vue项目使用Docker+Jenkinsfile方式
前端·vue.js·jenkins
荔枝荔枝荔枝12 小时前
【Vue源码学习】Vue新手友好!为什么vue2 this能够直接获取到data和methods中的属性?
vue.js·源码
寻觅~流光12 小时前
封装---统一封装处理页面标题
开发语言·前端·javascript·vue.js·typescript·前端框架·vue
江上暮云12 小时前
手摸手带你彻底搞懂Vue的响应式原理
vue.js
恰薯条的屑海鸥13 小时前
前端进阶之路-从传统前端到VUE-JS(第五期-路由应用)
前端·javascript·vue.js·学习·前端框架
wangpq13 小时前
Echart饼图自动轮播效果封装
javascript·vue.js