自学内容网 自学内容网

自己实现一个popup弹窗

实现一个手机端的带蒙版的浮层弹窗
popup.ts这个文件是缓存示例在打开其他弹窗时隐藏之前展示的浮层

const popupInstanceMap: any[] = []
export function createPopupInstance(scopeId: string, instance: any) {
  return popupInstanceMap.push({ instance, scopeId })
}
export const deletePopupInstance = (scopeId: string) => {
  const instanceIndex = popupInstanceMap.findIndex(item => item.scopeId === scopeId)
  if (instanceIndex == -1) {
    popupInstanceMap.splice(instanceIndex, 1)
  }
}
export const getOtherPopupInstance = (scopeId: string) => {
  const instanceList = popupInstanceMap.filter(item => item.scopeId !== scopeId).map(item => item.instance)
  return instanceList
}


popup组件

<template>
  <div class="custom-popup-container">
    <div class="reference-container" ref="referenceRef">
      <slot name="reference"></slot>
    </div>
    <Teleport to="body" v-if="visiblePopup">
      <div class="popup_box" :style="{ height: popupRefTop + 'px' }" ref="popupRef">
        <div class="popup_mask" @click.stop="closeModal"></div>
        <div class="popup-content">
          <slot></slot>
        </div>
      </div>
    </Teleport>
  </div>
</template>
<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref, watch, getCurrentInstance } from 'vue'
import { createPopupInstance, deletePopupInstance, getOtherPopupInstance } from './popup'

const visiblePopup = defineModel<boolean>()
const emit = defineEmits(['close'])

const referenceRef = ref<any>(null)
const popupRef = ref<any>(null)

const popupRefTop = ref(0)
const instance = getCurrentInstance()
const scopdeId = ref('')
/** *************** method ************** **/

const showPopUp = () => {
  const referenceNode = referenceRef.value
  const rect = referenceNode.getBoundingClientRect()
  const viewHeight = document.body.clientHeight
  const popupTop = viewHeight - rect.top - rect.height
  popupRefTop.value = popupTop
}

const closeModal = () => {
  visiblePopup.value = false
  emit('close')
}
watch(
  visiblePopup,
  val => {
    if (val) {
      getOtherPopupInstance(scopdeId.value).map(item => {
        item.exposed.closeModal()
      })
      showPopUp()
    }
  },
  {
    immediate: true
  }
)
/** **************** life cycle************* **/
onMounted(() => {
  scopdeId.value = Math.random().toString(36).substr(2, 10)
  createPopupInstance(scopdeId.value, instance)
})
onBeforeUnmount(() => {
  deletePopupInstance(scopdeId.value)
})

defineExpose({
  closeModal,
  visiblePopup
})
</script>
<style lang="scss" scoped>
.popup_box {
  position: fixed;
  width: 100%;
  bottom: 0;
  z-index: 1000;
}
.popup_mask {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.3);
}
.popup-content {
  position: relative;
  z-index: 1;
  border-radius: 0 0 8px 8px;
  background-color: #ffffff;
  padding: 10px 12px;
}
</style>

使用组件方法
dome.vue

<Popup class="status" v-model="visibleStatusModal">
        <template #reference>
          <div class="dropdown_menu_box">
            <span class="menu_text" @click="visibleStatusModal = true">
              {{ getOptionText(curStatus, statusOptList) }}
            </span>
            <van-icon class="arrow" :class="visibleStatusModal ? 'active_icon' : ''" name="arrow-down" />
          </div>
        </template>
        <div class="status_list">
          <div
            class="status_item"
            :class="option.value == curStatus ? 'active_item' : ''"
            v-for="option in statusOptList"
            :key="option.label"
            @click="statusChangeHandle(option)"
          >
            {{ option.label }}
          </div>
        </div>
      </Popup>
<script setup lang="ts">
import { ref } from 'vue'
import Popup from './components/Popup.vue'

const curStatus = ref<string>('')
const statusOptList = ref<any[]>([
  { label: '全部', value: '' },
  { label: '在售', value: '1' },
  { label: '停售', value: '2' }
])
const visibleStatusModal = ref(false)
/*************  methods **********/
const statusChangeHandle = opt => {
  curStatus.value = opt.value
}
</script>

domo页面视图
在这里插入图片描述


原文地址:https://blog.csdn.net/qq_36208612/article/details/144109945

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!