ykt-team-wxapp/components/full-page.vue
2026-01-30 14:25:36 +08:00

92 lines
1.8 KiB
Vue

<template>
<view class="full-page" :style="pageStyle">
<view v-if="hasHeader" class="page-header">
<slot name="header"></slot>
</view>
<view class="page-main" :style="mainStyle">
<view v-if="customScroll" class="page-scroll">
<slot></slot>
</view>
<scroll-view
v-else
scroll-y="true"
:scroll-top="scrollTop"
class="page-scroll"
@scrolltolower="scrolltolower"
@scroll="onScroll"
>
<slot></slot>
</scroll-view>
</view>
<view v-if="hasFooter" class="page-footer">
<slot name="footer"></slot>
</view>
<!-- #ifdef MP-->
<!-- <view class="safeareaBottom"></view> -->
<!-- #endif -->
</view>
</template>
<script setup>
import { computed, useSlots, ref } from "vue";
import useDebounce from "@/utils/useDebounce";
const emits = defineEmits(["reachBottom"]);
const props = defineProps({
customScroll: { type: Boolean, default: false },
mainStyle: { default: "" },
pageStyle: { default: "" },
});
const slots = useSlots();
const hasHeader = computed(() => !!slots.header);
const hasFooter = computed(() => !!slots.footer);
const scrollTop = ref(0);
const scrolltolower = useDebounce(() => {
emits("reachBottom");
});
const onScroll = useDebounce((e) => {
scrollTop.value = e.detail.scrollTop;
});
function scrollToBottom() {
scrollTop.value = 999999;
}
defineExpose({
scrollToBottom,
});
</script>
<style lang="scss" scoped>
.full-page {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.page-header,
.page-footer {
flex-shrink: 0;
}
.page-main {
flex-grow: 1;
position: relative;
}
.page-scroll {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.safeareaBottom {
flex-shrink: 0;
height: env(safe-area-inset-bottom);
}
</style>