VUE弹框组件(dialog组件)封装(基础功能、可传富文本)

VUE组件封装部分:Dialog.vue

<!-- 弹框组件组件 -->
<template>
  <div :class="dialogClass" class="warmPrompt">
    <van-dialog
      v-model="dialogShow"
      :closeOnClickOverlay="closeOnClickOverlay"
      :overlay="overlay"
      :show-confirm-button="false"
      width="3rem"
    >
      <div class="warmPrompt_content">
        <div class="warmPrompt_content_title">{{ title }}</div>

        <div ref="content_static_wrapper" :style="boxShadow" class="warmPrompt_content_text">
          <div ref="content_scroll_wrapper" :style="{'textAlign': textAlign}">
            <div v-if="text">{{ text }}</div>

            <div v-if="textMini !== ''" class="warmPrompt_content_text--mini">{{ textMini }}</div>

            <div v-if="textHtml" v-html="textHtml"></div>
          </div>
        </div>

        <div class="warmPrompt_content_button">
          <van-button v-if="cancelButtonShow"
                      :color="cancelBtnColor"
                      block
                      class="cancelButton"
                      plain
                      @click="cancel">
            {{ cancelButtonText }}
          </van-button>
          <van-button :color="confirmBtnColor"
                      block
                      class="confirmButton"
                      plain @click="confirm">
            {{ confirmButtonText }}
          </van-button>
        </div>
      </div>
    </van-dialog>
  </div>
</template>

<script>
export default {
  name: 'Dialog',
  props: {
    show: {
      type: Boolean,
      default: false
    },

    title: {
      type: String,
      default: '温馨提示'
    },

    text: {
      type: String,
      default: ''
    },

    textHtml: {
      type: String,
      default: ''
    },

    textMini: {
      type: String,
      default: ''
    },

    textAlign: {
      type: String,
      default: 'left'
    },

    confirmButtonText: {
      type: String,
      default: '确认'
    },

    cancelButtonShow: {
      type: Boolean,
      default: true
    },

    cancelButtonText: {
      type: String,
      default: '取消'
    },

    overlay: {
      type: Boolean,
      default: true
    },

    closeOnClickOverlay: {
      type: Boolean,
      default: false
    },

    closeOnPopstate: {
      type: Boolean,
      default: false
    },

    cancelBtnColor: {
      type: String,
      default: '#212634'
    },

    confirmBtnColor: {
      type: String,
      default: '#FF4536'
    },

    dialogClass: {
      type: String,
      default: ''
    }
  },

  data () {
    return {
      boxShadow: '' // 内容可滚动阴影
    }
  },
  computed: {
    dialogShow: {
      get () {
        return this.show
      },
      set (val) {
        this.$emit('update', val)
      }
    }
  },
  watch: {
    // 监控内容数据判断是否产生阴影
    textHtml: {
      handler (newVal, oldVal) {
        if (newVal) {
          this.$nextTick(() => {
            let height1 = this.$refs.content_static_wrapper.getBoundingClientRect()
              .height
            let height2 = this.$refs.content_scroll_wrapper.getBoundingClientRect()
              .height
            if (height2 > height1) {
              this.boxShadow = 'box-shadow: 0 -0.1rem 0.1rem -0.1rem #d3d4d6 inset;'
            } else {
              this.boxShadow = ''
            }
          })
        }
      },
      immediate: true
    },
    text: {
      handler (newVal, oldVal) {
        if (newVal) {
          this.$nextTick(() => {
            let height1 = this.$refs.content_static_wrapper.getBoundingClientRect()
              .height
            let height2 = this.$refs.content_scroll_wrapper.getBoundingClientRect()
              .height
            if (height2 > height1) {
              this.boxShadow = 'box-shadow: 0 -0.1rem 0.1rem -0.1rem #d3d4d6 inset;'
            } else {
              this.boxShadow = ''
            }
          })
        }
      },
      immediate: true
    },
    textMini: {
      handler (newVal, oldVal) {
        if (newVal) {
          this.$nextTick(() => {
            let height1 = this.$refs.content_static_wrapper.getBoundingClientRect()
              .height
            let height2 = this.$refs.content_scroll_wrapper.getBoundingClientRect()
              .height
            if (height2 > height1) {
              this.boxShadow = 'box-shadow: 0 -0.1rem 0.1rem -0.1rem #d3d4d6 inset;'
            } else {
              this.boxShadow = ''
            }
          })
        }
      },
      immediate: true
    }
  },

  // 方法集合
  methods: {
    // 点击确认按钮
    confirm () {
      this.$emit('click')
    },
    // 点击取消按钮
    cancel () {
      this.$emit('close')
    }
  }
}
</script>

<style lang='scss' scoped>
/* 使用$符号可以标识一个变量;@import url(); 引入公共css类 */
@import "src/styles/variable";

.warmPrompt {
  font-size: 0.14rem;
  text-align: center;
  line-height: 1;

  &_content {
    // padding: 0.2rem 0.2rem 0;
    ::-webkit-scrollbar {
      display: none;
    }

    &_title {
      font-size: 0.18rem;
      font-weight: 700;
      color: #212634;
      letter-spacing: 0.02rem;
      padding: 0.3rem 0.15rem 0.1rem;
    }

    &_text {
      font-size: 0.16rem;
      color: #7A7D85;
      letter-spacing: 0.0015rem;
      line-height: 1.5;
      max-height: 3.8rem;
      overflow-y: scroll;
      text-align: left;
      padding: 0 0.2rem;
      pointer-events: all;
      word-wrap: break-word;

      /deep/ p {
        margin: 0 0 0.1rem;
        // margin-block-start: 0.1rem;
        // margin-block-end: 0;
      }

      &--mini {
        margin-top: 0.1rem !important;
        font-size: 0.12rem;
        color: #666666;
        letter-spacing: 0.0013rem;
      }
    }

    &_button {
      padding: 0.16rem 0 0.06rem;
      display: flex;
      justify-content: space-between;
      align-items: center;

      /deep/ .van-button::before {
        background-color: unset;
      }

      /deep/ .van-button--block {
        height: 0.36rem;
        line-height: 0.36rem;
        font-size: 0.16rem;
        padding: 0;
      }
    }
  }
}

.newDialogClass {

  /deep/ .van-dialog {
    border-radius: 12 * $px3;
    width: 320 * $px3 !important;
  }

  .warmPrompt_content {
    &_title {
      padding: 30 * $px3 15 * $px3 10 * $px3;
      letter-spacing: 0;
    }

    &_text {
      color: #212634;
    }

    &_button {
      display: flex;
      flex-direction: column-reverse;
      justify-content: center;
      align-items: center;
      padding: 20 * $px3 0 30 * $px3;

      .confirmButton {
        height: 48 * $px3;
        width: 240 * $px3;
        background-image: linear-gradient(90deg, #FF3F3F 3%, #FB234D 100%);
        border-radius: 100 * $px3;
        font-size: 18 * $px3 !important;
        color: #FFFFFF !important;
        font-weight: 700;
      }

      .cancelButton {
        margin-top: 20 * $px3;
        height: 20 * $px3;
        width: 240 * $px3;
        font-size: 18 * $px3 !important;
        color: #7A7D85 !important;
        font-weight: 700;
      }
    }
  }
}
</style>

js封装部分:dialog-plugin.js

import Dialog from '@/components/WarmPrompt'

let $vm
const defaultOptions = {
  show: false,
  title: '温馨提示',
  text: '',
  textHtml: '',
  textMini: '',
  textAlign: '',
  confirmButtonText: '确认',
  cancelButtonText: '取消',
  cancelButtonShow: true,
  closeOnPopstate: true,
  overlay: true, // 是否展示遮罩层
  closeOnClickOverlay: false, // 是否在点击遮罩层后关闭弹窗
  onClick: null,
  onClose: null,
  bgColor: '#D23228',
  cancelBtnColor: '#212634', // 取消按钮颜色
  confirmBtnColor: '#FF4536', // 确认按钮颜色
  dialogClass: '' // 弹框类名(新的按钮弹框样式)
}

Dialog.install = function (Vue, options = {}) {
  Vue.component(Dialog.name, Dialog)
  if (!$vm) {
    const PropsData = Object.assign({}, defaultOptions, options)
    const {
      show,
      title,
      text,
      textHtml,
      textMini,
      textAlign,
      confirmButtonText,
      cancelButtonText,
      cancelButtonShow,
      closeOnPopstate,
      overlay,
      closeOnClickOverlay,
      bgColor,
      cancelBtnColor,
      confirmBtnColor,
      dialogClass
    } = PropsData

    $vm = new Vue({
      el: document.createElement('div'),
      data () {
        return {
          showAttr: show,
          titleAttr: title,
          textAttr: text,
          textHtmlAttr: textHtml,
          textMiniAttr: textMini,
          textAlignAttr: textAlign,
          confirmButtonTextAttr: confirmButtonText,
          cancelButtonTextAttr: cancelButtonText,
          cancelButtonShowAttr: cancelButtonShow,
          closeOnPopstateAttr: closeOnPopstate,
          overlayAttr: overlay,
          closeOnClickOverlayAttr: closeOnClickOverlay,
          bgColorAttr: bgColor,
          cancelBtnColorAttr: cancelBtnColor,
          confirmBtnColorAttr: confirmBtnColor,
          dialogClassAttr: dialogClass
        }
      },
      render (h) {
        const {
          showAttr,
          titleAttr,
          textAttr,
          textHtmlAttr,
          textMiniAttr,
          textAlignAttr,
          confirmButtonTextAttr,
          cancelButtonTextAttr,
          cancelButtonShowAttr,
          closeOnPopstateAttr,
          overlayAttr,
          closeOnClickOverlayAttr,
          onClick,
          onClose,
          bgColorAttr,
          cancelBtnColorAttr,
          confirmBtnColorAttr,
          dialogClassAttr
        } = this
        return h(Dialog, {
          attrs: {
            show: showAttr,
            title: titleAttr,
            text: textAttr,
            textHtml: textHtmlAttr,
            textMini: textMiniAttr,
            textAlign: textAlignAttr,
            confirmButtonText: confirmButtonTextAttr,
            cancelButtonText: cancelButtonTextAttr,
            cancelButtonShow: cancelButtonShowAttr,
            closeOnPopstate: closeOnPopstateAttr,
            overlay: overlayAttr,
            closeOnClickOverlay: closeOnClickOverlayAttr,
            bgColor: bgColorAttr,
            cancelBtnColor: cancelBtnColorAttr,
            confirmBtnColor: confirmBtnColorAttr,
            dialogClass: dialogClassAttr
          },

          on: {
            click: () => {
              if (onClick) onClick()
            },
            close: () => {
              this.showAttr = false
              if (onClose) onClose()
            },
            update: (val) => {
              this.showAttr = val
            }
          }
        })
      },
      methods: {
        show (opt = {}) {
          console.log('已经调用了show方法')
          const mergeObj = Object.assign({}, PropsData, { show: true }, opt)
          const {
            onClick,
            onClose,
            ...otherProps
          } = mergeObj
          Object.keys(otherProps).forEach(key => {
            this[`${key}Attr`] = otherProps[key]
          })

          this.onClick = onClick
          this.onClose = onClose
        },

        hide () {
          this.showAttr = false
        },

        isShow () {
          return this.showAttr
        },

        update (val) {
          this.showAttr = val
        }
      }
    })
    document.body.appendChild($vm.$el)
  }

  const { show, hide, isShow, update } = $vm

  Vue.dialog = Vue.prototype.$dialog = {
    show,
    hide,
    isShow,
    update
  }
}

export default Dialog

添加自定义组件:main.js

/* 添加自定义dialog插件 */
import Dialog from '@/plugins/dialog-plugin'
Vue.use(Dialog)

调用Dialog弹框组件

this.$dialog.show({
        title: '弹框名称',
        textHtml: `<div>
      <div style="font-size: 0.14rem; color: #222222; margin-top: 0.1rem; text-align: left">这是一段富文本</div>
    </div>`,
        confirmButtonText: '确认按钮',
        cancelButtonText: '取消按钮',
        onClick: () => {
        // 确认按钮点击操作
          this.$dialog.hide() // 隐藏弹框
        },
        onClose: () => {
          // 取消按钮点击操作
        }
      })
  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,你需要在父组件中引入 Dialog 弹框组件,并在父组件的 template 中添加一个触发显示弹框的按钮。例如: ```vue <template> <div> <button @click="showDialog">显示弹框</button> <Dialog v-model="dialogVisible"></Dialog> </div> </template> ``` 在上面的代码中,我们添加了一个按钮,当用户点击该按钮时,会触发 showDialog 方法。同时,我们引入了一个名为 Dialog组件,并将它的显示与隐藏与一个名为 dialogVisible 的变量绑定了起来。 接下来,在父组件的 script 中,我们需要定义 showDialog 方法以及 dialogVisible 变量。例如: ```vue <script> import Dialog from './Dialog.vue' export default { components: { Dialog }, data() { return { dialogVisible: false } }, methods: { showDialog() { this.dialogVisible = true } } } </script> ``` 在上面的代码中,我们首先引入了 Dialog 组件,然后在 data 中定义了 dialogVisible 变量,并将其默认值设置为 false。接着,我们定义了一个名为 showDialog 的方法,该方法将 dialogVisible 设置为 true,从而显示 Dialog 弹框组件。 最后,我们需要在 Dialog 弹框组件中添加一个关闭按钮,并将其与 dialogVisible 变量绑定起来。例如: ```vue <template> <div> <div class="dialog-mask" v-if="visible" @click="close"></div> <div class="dialog-wrapper" v-if="visible"> <div class="dialog-content"> <div class="dialog-header"> <h3 class="dialog-title">Dialog 标题</h3> <button class="dialog-close-btn" @click="close">×</button> </div> <div class="dialog-body"> <p>Dialog 内容</p> </div> </div> </div> </div> </template> <script> export default { props: { visible: { type: Boolean, required: true } }, methods: { close() { this.$emit('update:visible', false) } } } </script> ``` 在上面的代码中,我们添加了一个名为 close 的方法,该方法会将 dialogVisible 设置为 false,并通过 $emit 方法将更新后的值传递给父组件。同时,我们在弹框组件中添加了一个关闭按钮,并在按钮的 click 事件中调用 close 方法。 这样,当用户点击父组件中的按钮时,就会触发 showDialog 方法,从而显示 Dialog 弹框组件。当用户点击弹框中的关闭按钮时,会触发 close 方法,从而关闭弹框

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值