perf: optimization of tabbar display (#4169)

* perf: optimization of tabbar display

* fix: ci error

* chore: typo

* chore: typo
This commit is contained in:
Vben
2024-08-16 22:20:18 +08:00
committed by GitHub
parent 8987067b5a
commit 0faf7810b6
38 changed files with 710 additions and 504 deletions

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref } from 'vue';
import { computed, ref } from 'vue';
import { cn } from '@vben-core/shared';
@@ -11,6 +11,10 @@ interface Props {
scrollBarClass?: any;
shadow?: boolean;
shadowBorder?: boolean;
shadowBottom?: boolean;
shadowLeft?: boolean;
shadowRight?: boolean;
shadowTop?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
@@ -18,29 +22,66 @@ const props = withDefaults(defineProps<Props>(), {
horizontal: false,
shadow: false,
shadowBorder: false,
shadowBottom: true,
shadowLeft: false,
shadowRight: false,
shadowTop: true,
});
const emit = defineEmits<{
scrollAt: [{ bottom: boolean; left: boolean; right: boolean; top: boolean }];
}>();
const isAtTop = ref(true);
const isAtRight = ref(false);
const isAtBottom = ref(false);
const isAtLeft = ref(true);
const showShadowTop = computed(() => props.shadow && props.shadowTop);
const showShadowBottom = computed(() => props.shadow && props.shadowBottom);
const showShadowLeft = computed(() => props.shadow && props.shadowLeft);
const showShadowRight = computed(() => props.shadow && props.shadowRight);
const computedShadowClasses = computed(() => ({
'shadow-both':
!isAtLeft.value &&
!isAtRight.value &&
showShadowLeft.value &&
showShadowRight.value,
'shadow-left': !isAtLeft.value && showShadowLeft.value,
'shadow-right': !isAtRight.value && showShadowRight.value,
}));
function handleScroll(event: Event) {
const target = event.target as HTMLElement;
const scrollTop = target?.scrollTop ?? 0;
const scrollLeft = target?.scrollLeft ?? 0;
const offsetHeight = target?.offsetHeight ?? 0;
const offsetWidth = target?.offsetWidth ?? 0;
const scrollHeight = target?.scrollHeight ?? 0;
const scrollWidth = target?.scrollWidth ?? 0;
isAtTop.value = scrollTop <= 0;
isAtLeft.value = scrollLeft <= 0;
isAtBottom.value = scrollTop + offsetHeight >= scrollHeight;
isAtRight.value = scrollLeft + offsetWidth >= scrollWidth;
emit('scrollAt', {
bottom: isAtBottom.value,
left: isAtLeft.value,
right: isAtRight.value,
top: isAtTop.value,
});
}
</script>
<template>
<ScrollArea
:class="[cn(props.class)]"
:class="[cn(props.class), computedShadowClasses]"
:on-scroll="handleScroll"
class="relative"
class="vben-scrollbar relative"
>
<div
v-if="shadow"
v-if="showShadowTop"
:class="{
'opacity-100': !isAtTop,
'border-border border-t': shadowBorder && !isAtTop,
@@ -49,7 +90,7 @@ function handleScroll(event: Event) {
></div>
<slot></slot>
<div
v-if="shadow"
v-if="showShadowBottom"
:class="{
'opacity-100': !isAtTop && !isAtBottom,
'border-border border-b': shadowBorder && !isAtTop && !isAtBottom,
@@ -65,6 +106,31 @@ function handleScroll(event: Event) {
</template>
<style scoped>
.vben-scrollbar {
&:not(.shadow-both).shadow-left {
mask-image: linear-gradient(90deg, transparent, #000 16px);
}
&:not(.shadow-both).shadow-right {
mask-image: linear-gradient(
90deg,
#000 0%,
#000 calc(100% - 16px),
transparent
);
}
&.shadow-both {
mask-image: linear-gradient(
90deg,
transparent,
#000 16px,
#000 calc(100% - 16px),
transparent 100%
);
}
}
.scrollbar-top-shadow {
background: linear-gradient(
to bottom,