Creación de un componente uni-app hello-popup desde cero

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>

Etiquetas: uni-app vue.js componentes popups css

Publicado el 6-17 02:56