Para implementar un popup en uni-app que tenga un título fijo en la parte superior, botones de confimrar y cancelar en la inferior, y un área de contenido con altura dinámica que no exceda el 80% de su cotnenedor padre, se puede crear un componente personalizado. El contenedor padre, a su vez, debe limitar su altura máxima al 80% de su propio padre.
A continuación, se muestra el código del componente hello-popup.vue con una estructura reestructurada:
<template>
<view v-if="isVisible" :class="['overlay', animationClass]" @tap.stop="closePopup">
<view :class="['dialog', 'centered', animationClass]" @tap.stop="handleDialogClick">
<view class="popup-title">
{{ popupTitle }}
</view>
<view class="popup-content">
<slot />
</view>
<view class="button-group">
<button class="button-item" type="default" @tap="closePopup">Cancelar</button>
<button class="button-item" type="primary" @tap="onConfirm">Aceptar</button>
</view>
</view>
</view>
</template>
<script>
export default {
name: "CustomPopup",
props: {
popupTitle: {
type: String,
defaultValue: 'Título por defecto',
},
},
data() {
return {
isVisible: false,
animationClass: '',
};
},
methods: {
openPopup() {
this.isVisible = true;
this.$nextTick(() => {
setTimeout(() => {
this.animationClass = 'animate-in';
}, 30);
});
},
closePopup() {
this.animationClass = '';
this.$nextTick(() => {
setTimeout(() => {
this.isVisible = false;
}, 300);
});
},
handleDialogClick() {
// Lógica para manejar clics dentro del diálogo, si es necesario
},
onConfirm() {
this.$emit('confirm');
},
},
};
</script>
<style scoped>
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: opacity 0.3s ease;
}
.overlay.animate-in {
opacity: 1;
}
.dialog {
max-height: 3%;
width: 3%;
opacity: 0;
transition: all 0.3s ease;
}
.dialog.animate-in {
max-height: 80%;
width: 80%;
opacity: 1;
display: flex;
flex-direction: column;
background-color: #fff;
border-radius: 12px;
padding: 16px;
overflow: hidden;
}
.centered {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.popup-content {
width: 100%;
max-height: 80%;
overflow-y: auto;
}
.popup-title {
text-align: center;
font-size: 18px;
font-weight: bold;
}
.button-group {
display: flex;
justify-content: space-around;
margin-top: 20px;
padding: 10px 0;
}
.button-item {
flex: 1;
margin: 0 5px;
}
</style>
Para usar este componente en una página, se importa y se invoca mediante una referencia. Aquí un ejemplo modificado:
<template>
<view>
<button @tap="launchPopup">Mostrar Popup</button>
<custom-popup ref="popupRef" :popupTitle="currentTitle" @confirm="handleConfirmation">
<view v-for="(item, idx) in listItems" :key="idx">
<text>Elemento {{ idx }}</text>
</view>
<view>
Nota: Este es un contenido dinámico para el popup.
</view>
</custom-popup>
</view>
</template>
<script>
import CustomPopup from '@/components/custom-popup.vue';
export default {
components: {
CustomPopup,
},
data() {
return {
currentTitle: '',
listItems: Array.from({ length: 8 }, (_, i) => i),
};
},
methods: {
launchPopup() {
this.currentTitle = "ejemplo.titulo.com";
this.$refs.popupRef.openPopup();
},
handleConfirmation() {
console.log('Acción confirmada');
this.$refs.popupRef.closePopup();
},
},
};
</script>