ykt-wxapp/components/full-page.vue

87 lines
1.7 KiB
Vue
Raw Normal View History

2026-01-19 18:52:18 +08:00
<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>