需求

看了半天uniapp官方提供的插件,发现就是没有dialog弹窗的封装,有点难受,这个弹窗其实用的地方还挺多的, 但是uni-popup组件的用法实在是有点粗暴啊,需要通过ref获取popup组件实例,操作组件实例的open和close方法实现开关,和我们日常的v-model绑定差了好多,于是自己想着造一个。

在网页端我们watch监听props的变量,然后在nextTick会调中使用popup组件实例是没有问题的,但是在微信小程序中发现这个方法有一个问题?

如果我这个弹窗默认就是true打开的状态,那么在watch中即便使用了nextTick我们也无法获取到组件的实例,这个不知道是不是bug,反正我的解决办法就是在弹窗的首次处理时在onMounted钩子下处理。

代码

<template>
  <uni-popup ref="popup" type="center" :mask-click="false" background-color="transparent" @maskClick="onMaskClick">
    <view class="customer-service-dialog">xsadasxx</view>
  </uni-popup>
</template>

<script lang="ts">
import { defineComponent, ref, computed, watch, nextTick, onMounted } from "vue";

export default defineComponent({
  props: {
    /** 是否显示弹窗 */
    show: {
      type: Boolean,
      required: true,
    },
    /** 是否允许点击遮罩层关闭弹窗 */
    maskClosable: {
      type: Boolean,
      default: true,
    },
  },
  emits: ["update:show"],
  setup(props, { emit }) {
    /** 是否初始化
     * 由于在微信小程序中watch的监听即便使用了nextTick也会在onMounted之前执行
     * 此时通过ref获取的popup还是undefined
     * 所以需要通过此变量来判断是否初始化
     */
    let init = false;
    const popup = ref<Popup>();

    /** 遮罩层点击事件 */
    function onMaskClick() {
      if (props.maskClosable) {
        emit("update:show", false);
      }
    }

    /** 监听是否显示 */
    watch(
      () => props.show,
      (val) => {
        if (!init) return;
        if (val) {
          nextTick(() => {
            popup.value?.open();
          });
        } else {
          popup.value?.close();
        }
      }
    );

    onMounted(() => {
      init = true;
      if (props.show) {
        popup.value?.open();
      }
    });

    return {
      popup,
      onMaskClick,
    };
  },
});
</script>

<style scoped></style>

在外部使用的时候我们就可以通过双向绑定的方式实现弹窗的展示了。

<CustomerServiceDialog v-model:show="openCustomerServiceDialog" />

组件名这些就不多说了,写过vue的应该都知道。

分类: UNI-APP 标签: dialog弹窗组件

评论

全部评论 2

  1. 杰哥
    杰哥
    Google Chrome Windows 10
    杰哥,也开始uni-app了吗?

    加入光荣的进化~

    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @杰哥嗐,时势造英雄

目录