自己实现一个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)!