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

相关推荐
小新1109 小时前
从零开始 Vue.js
前端·javascript·vue.js
naildingding10 小时前
Vue基础核心
前端·vue.js
搬砖的阿wei10 小时前
Pinia 与 Vuex 区别
前端·vue.js
用户154471843963112 小时前
从零实现一个vue2项目
vue.js
OpenTiny社区12 小时前
一行命令添加 AI 对话入口!TinyRobot 也太省事了~
前端·vue.js·ai编程
sagima_sdu12 小时前
Vue 前端径向渐变背景制作
前端·javascript·vue.js
叶落阁主13 小时前
Vue3 后台管理系统全局菜单搜索实战:Cmd/Ctrl + K、权限菜单与拼音过滤
前端·javascript·vue.js
MacroZheng13 小时前
阿里Qoder + GLM-5.1,夯爆了!
前端·vue.js·人工智能
AKA__老方丈14 小时前
删除确认 Hook - 统一管理单删/批量删除的确认弹窗与执行
前端·javascript·vue.js
布兰妮甜15 小时前
Vue 项目 `localhost:3000` 打不开?404 常见原因排查指南
前端·javascript·vue.js·vuecli·4040排查