微信小程序封装公共弹窗dailog组件-UNIAPP篇

在小程序的开发过程中,会发现弹框这东西使用频率太高了,能不能封装一个公共组件呢~ 答案当然是能!!! 开发思路借鉴了一下vant,有兴趣的同学可以,研究一下

在小程序的开发过程中,会发现弹框这东西使用频率太高了,能不能封装一个公共组件呢~ 答案当然是能!!!

开发思路借鉴了一下vant,有兴趣的同学可以,研究一下 https://github.com/youzan/vant-weapp/tree/dev/dist/dialog

大概思路通过selectComponent获取到组件,然后传入对应参数,

代码实现

创建dialog.js

const Dialog = (options) => {
   return new Promise((resolve, reject) => {
      const pages = getCurrentPages();
      const getContext = pages[pages.length - 1];
      let dialog = getContext.selectComponent("#e-dialog").$vm;
      if (dialog) {
         //dialog.show(config);
         options.callback = (action, instance) => {
            action === "confirm" ? resolve(instance) : reject(instance);
         };
         dialog.show(options);
      } else {
         console.warn("未找到 e-dialog 节点,请确认 selector 及 context 是否正确");
      }
   });
};
Dialog.alert = (options) => Dialog(options);
Dialog.confirm = (options) => Dialog(Object.assign({ showCancelButton: true }, options));
export default Dialog;

dialog.vue

<template>
   <!--dialog-modal-->
   <view class="dialog-modal" :class="[modalVisible ? 'show' : '']">
      <view class="flex">
         <view class="box" :animation="animationData">
            <view class="modal-title">
               {{ configData.title }}
            </view>
            <view :class="`${configData.className} modal-desc`">
               <block v-if="configData.isHtml">
                  <view class="text-html">
                     <rich-text :nodes="configData.content"></rich-text>
                  </view>
               </block>
               <block v-else>
                  <text class="text">{{ configData.content }}</text>
               </block>
            </view>
            <view class="modal-btn" :class="[configData.showCancelButton == false ? 'wid100' : '']">
               <block v-if="configData.showCancelButton">
                  <button class="btn" @click="onCancel">{{ configData.cancelText }}</button>
               </block>
               <button class="confirm btn" @click="onConfirm">{{ configData.confirmText }}</button>
            </view>
         </view>
      </view>
   </view>
</template>
<script setup>
   import { ref, watch, getCurrentInstance, nextTick } from "vue";
   const props = defineProps({
      visible: {
         type: Boolean,
         default: false,
      },
      title: {
         type: String,
         default: "提示",
      },
      content: {
         type: String,
         default: "",
      },
      className: {
         type: String,
         default: "text-center",
      },
      isHtml: {
         type: Boolean,
         default: false,
      },
      showCancelButton: {
         type: Boolean,
         default: false,
      },
      cancelText: {
         type: String,
         default: "取消",
      },
      confirmText: {
         type: String,
         default: "确定",
      },
   });
   const instance = getCurrentInstance();
   const callback = ref(() => {});
   const modalVisible = ref(false);
   const configData = ref(props);
   const animation = uni.createAnimation({
      duration: 200,
      timingFunction: "ease",
   });
   const animationData = ref(null);
   watch(
      () => props.visible,
      (newProps) => {
         if (newProps == true) {
            setTimeout(() => {
               modalVisible.value = true;
               animation.scale(1).opacity(1).step();
               animationData.value = animation.export();
            }, 100);
         } else {
            modalVisible.value = false;
         }
      },
      { immediate: true }
   );
   const emit = defineEmits(["cancel", "confirm"]);
   const onCancel = function () {
      handleAction("cancel");
      // animation.scale(0).opacity(0).step();
      // animationData.value = animation.export();
      // setTimeout(() => {
      //    emit("cancel");
      // }, 100);
   };
   const onConfirm = function () {
      handleAction("confirm");
      // animation.scale(0).opacity(0).step();
      // animationData.value = animation.export();
      // setTimeout(() => {
      //    emit("ok");
      // }, 100);
   };
   const show = (data) => {
      callback.value = !data.callback ? () => {} : data.callback;
      modalVisible.value = true;
      animation.scale(1).opacity(1).step();
      animationData.value = animation.export();
      configData.value = Object.assign(
         {},
         {
            title: data.title ?? "提示",
            content: data.content ?? "",
            cancelText: data.cancelText ?? "取消",
            confirmText: data.confirmText ?? "确定",
            showCancelButton: data.showCancelButton ?? false,
            isHtml: data.isHtml ?? false,
            className: data.className ?? "text-center",
         }
      );
   };
   const handleAction = (action) => {
      emit(action, instance);
      closeDailog(action);
   };
   const closeDailog = (action) => {
      modalVisible.value = false;
      animation.scale(0).opacity(0).step();
      animationData.value = animation.export();
      setTimeout(function () {
         nextTick(() => {
            if (callback.value) {
               callback.value(action, instance);
            }
         });
      }, 100);
   };
   defineExpose({
      show,
   });
</script>
<style lang="less" scoped>
   .dialog-modal {
      position: fixed;
      background-color: rgba(0, 0, 0, 0.5);
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      opacity: 0;
      transition: all 0.3s ease;
      visibility: hidden;
      z-index: 3;

      .flex {
         width: 100%;
         height: 100%;
         display: flex;
         align-items: center;
         justify-content: center;

         .box {
            background-color: #ffffff;
            border-radius: 20rpx;
            padding: 40rpx;
            width: 65%;
            text-align: center;
            font-size: 28rpx;
            transform: scale(0);
            opacity: 0;

            .modal-title {
               font-size: 32rpx;
               font-weight: bold;
               color: var(--zpyj-text-main-color);
            }

            .modal-desc {
               margin: 30rpx 0;

               .text {
                  display: block;
                  line-height: 44rpx;
                  color: #666666;
                  font-size: 28rpx;
               }

               .text-html {
                  line-height: 44rpx;
               }

               &.text-left {
                  text-align: left;
               }

               &.text-center {
                  text-align: center;
               }
            }

            .modal-btn {
               display: flex;
               align-items: center;
               justify-content: space-between;

               .btn {
                  all: unset;
                  width: 220rpx;
                  line-height: 88rpx;
                  display: block;
                  background-color: #ebf5ff;
                  border-radius: 10rpx;
                  border-color: #ebf5ff;
                  font-size: 32rpx;
                  margin: 0;
                  color: #008aff;
                  position: relative;

                  &.confirm {
                     background-color: #008aff;
                     border-color: #008aff;
                     color: #fff;
                  }
               }

               &.wid100 {
                  width: 100%;

                  .btn {
                     width: 100%;
                  }
               }
            }
         }
      }

      &.show {
         opacity: 1;
         visibility: inherit;
      }
   }
</style>

使用

<Dailog id="e-dialog"></Dailog>
import Dailog from "@/components/Dailog";

DailogClass.alert({ content: "提示信息" }).then(() => {
    //点击确定按钮
});
DailogClass.confirm({ content: "提示信息" }).then(() => {
    //点击确定按钮
}).catch(error => {
    //点击取消按钮
});

微信小程序原生和uniapp 的开发思路是一致的,只是需要吧uniapp 的语法改成微信小程序原生的写法即可

以上这篇微信小程序封装公共弹窗dailog组件-UNIAPP篇就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持芦苇派。

原创文章,作者:ECHO陈文,如若转载,请注明出处:https://www.luweipai.cn/html/1709262685/

  • 0