实现一个抽屉弹窗组件,支持传入px,%和vh,
<template>
<!-- <div class="pannel" :class="isOpen?'pannel-open':'pannel-close'" :style="styleObj"> -->
<div class="pannel" :style="styleObj" >
<button type='primary' size="mini" @click="closePannel">关闭pannel</button>
<view>弹窗内容</view>
<view>弹窗内容</view>
<view>弹窗内容</view>
<view>弹窗内容</view>
<view>弹窗内容</view>
<view>弹窗内容</view>
</div>
<!-- <div class="mask"></div> -->
</template>
<script setup>
import {
reactive,
ref,
computed,
watch,
onMounted
} from 'vue';
const isOpen = ref(false)
const emits = defineEmits(['close', 'update:modelValue'])
const props = defineProps({
modelValue: {
type: Boolean,
value: false
},
height:{
type: [String,Number],
value: '70vh'
}
})
const styleObj=reactive({
height:'70vh',
transform:`translateY(70vh)`
})
watch(()=>props.modelValue,(val)=>{
isOpen.value=val
emits("update:modelValue",val)
console.log("watch----n",val)
if(val){
console.log("watch---true")
styleObj.transform=`translateY(0vh)`;
}else{
console.log("watch---false")
setCloseTransformVal()
}
console.log("watch---style",styleObj)
})
const closePannel = () => {
isOpen.value =true
emits("update:modelValue",false)
}
const getHeight=()=>{
let height='70vh'
console.log("pannel--styleObj-props:-",props)
if(typeof(props.height)==='string'){
if(props.height.includes('%')||props.height.includes('vh') ){
console.log(11111)
height=props.height
}
}else{
console.log("非字符串")
height=props.height+'px'
}
return height
console.log("pannel--styleObj-height:-",height)
}
const setCloseTransformVal=()=>{
if(typeof(props.height)==='string'){
if(props.height.includes('%')){
styleObj.transform=`translateY(100%)`
}else{
styleObj.transform=`translateY(${props.height})`
}
}else{
styleObj.transform=`translateY(${props.height}px)`
}
}
onMounted(()=>{
styleObj.height=getHeight()
setCloseTransformVal()
})
</script>
<style scoped lang="scss">
.panne_wrap {
width: 100%;
// position: fixed;
// top:0;
// left: 0;
width: 100%;
height: 100vh;
background: #fff;
z-index: 10;
border-radius: 48rpx;
transform: translateY(70%);
}
.mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: rgab(0, 0, 0, 0.7);
z-index: 9;
}
.back_btn {
text-align: center;
padding: 20rpx;
}
.pannel {
transition: transform 0.3s ease-in-out;
width: 100%;
// height: 50vh;
position: fixed;
bottom: 0;
left: 0;
z-index: 1000;
background: #eee;
border-radius: 60rpx;
padding:40rpx;
box-sizing: border-box;
}
.pannel-open {
// height: 70vh;
transform: translateY(0vh);
}
.pannel-close {
// height: 0;
transform: translateY(70vh);
}
</style>
父组件使用:
、
<button type="primary" size="mini" @click="callPanel">唤起pannel</button>
<Pannel v-model="slideFlag" height="70vh"></Pannel>
const slideFlag = ref(false)
const callPanel = () => {
// debugger
slideFlag.value = true;
console.log("slideFlag.value:", slideFlag.value)
}