Commit eee7db61 authored by nick zheng's avatar nick zheng

fix: 应用预览及发布优化

parent 852687d7
import { ref } from 'vue' import { ref } from 'vue'
import { throttle } from 'lodash-es' import { throttle } from 'lodash-es'
import { MaybeComputedElementRef, useResizeObserver } from '@vueuse/core'
export function useBackBottom(cb: () => void) { export function useBackBottom(el: MaybeComputedElementRef, cb: () => void) {
const visible = ref(false) const visible = ref(false)
const lastScrollTop = ref(0) const lastScrollTop = ref(0)
// 点击回到底部
function clickBackBottom() { function clickBackBottom() {
visible.value = false visible.value = false
cb() cb()
} }
// 滚动处理逻辑
function handleScrollMessageContainer(e: Event) { function handleScrollMessageContainer(e: Event) {
const target = e.target as HTMLElement const target = e.target as HTMLElement
...@@ -28,7 +31,25 @@ export function useBackBottom(cb: () => void) { ...@@ -28,7 +31,25 @@ export function useBackBottom(cb: () => void) {
lastScrollTop.value = currentScrollTop lastScrollTop.value = currentScrollTop
} }
const throttleScrollMessageContainer = throttle(handleScrollMessageContainer, 100, { leading: true }) // 节流处理滚动事件
const throttleScrollContainer = throttle(handleScrollMessageContainer, 100, { leading: true })
return { visible, clickBackBottom, throttleScrollMessageContainer } // 节流处理容器resize事件
const throttledResizeCallback = throttle(
(entries) => {
const entry = entries[0]
const { clientHeight, scrollHeight } = entry.target
if (clientHeight >= scrollHeight && !visible.value) {
visible.value = false
}
},
300,
{ leading: true, trailing: true },
)
// 监听容器变化
useResizeObserver(el, throttledResizeCallback)
return { visible, clickBackBottom, throttleScrollContainer }
} }
<script setup lang="ts"> <script setup lang="ts">
import { nextTick, useTemplateRef, watch } from 'vue' import { nextTick, useTemplateRef } from 'vue'
import { ScrollbarInst } from 'naive-ui' import { ScrollbarInst } from 'naive-ui'
import MessageItem from './message-item.vue' import MessageItem from './message-item.vue'
import type { MessageItemInterface } from '../types' import type { MessageItemInterface } from '../types'
import { useBackBottom } from '@/composables/useBackBottom'
interface Props { interface Props {
messageList: Map<string, MessageItemInterface> messageList: Map<string, MessageItemInterface>
} }
const props = defineProps<Props>() defineProps<Props>()
defineExpose({ defineExpose({
scrollToBottom, scrollToBottom,
...@@ -17,45 +16,23 @@ defineExpose({ ...@@ -17,45 +16,23 @@ defineExpose({
const scrollbarRef = useTemplateRef<ScrollbarInst | null>('scrollbarRef') const scrollbarRef = useTemplateRef<ScrollbarInst | null>('scrollbarRef')
const { visible, clickBackBottom, throttleScrollMessageContainer } = useBackBottom(scrollToBottom)
function scrollToBottom() { function scrollToBottom() {
nextTick(() => { nextTick(() => {
if (scrollbarRef.value) { if (scrollbarRef.value) {
!visible.value && scrollbarRef.value.scrollTo({ top: 999999999, behavior: 'smooth' }) scrollbarRef.value.scrollTo({ top: 999999999, behavior: 'smooth' })
} }
}) })
} }
watch(
() => props.messageList.size,
() => {
clickBackBottom()
},
)
</script> </script>
<template> <template>
<div class="relative flex-1 overflow-hidden overflow-y-auto py-[20px]"> <div class="relative flex-1 overflow-hidden overflow-y-auto py-[20px]">
<n-scrollbar <n-scrollbar ref="scrollbarRef" class="min-h-full" content-class="min-h-full flex">
ref="scrollbarRef"
class="min-h-full"
content-class="min-h-full flex"
@scroll="throttleScrollMessageContainer"
>
<div class="flex flex-col-reverse overflow-hidden"> <div class="flex flex-col-reverse overflow-hidden">
<div class="pr-[10px]"> <div class="pr-[10px]">
<MessageItem v-for="[key, messageItem] in messageList" :key="key" :message-item="messageItem" /> <MessageItem v-for="[key, messageItem] in messageList" :key="key" :message-item="messageItem" />
</div> </div>
</div> </div>
<div
v-show="visible"
class="flex-center hover:text-theme-color absolute bottom-5 right-5 h-6 w-6 cursor-pointer rounded-full bg-white shadow-[0_0_0_1px_#ededed]"
@click.stop="clickBackBottom"
>
<i class="iconfont icon-decrease text-sm" />
</div>
</n-scrollbar> </n-scrollbar>
</div> </div>
</template> </template>
...@@ -22,7 +22,7 @@ defineEmits<{ ...@@ -22,7 +22,7 @@ defineEmits<{
const { scrollRef, scrollToBottom } = useScroll() const { scrollRef, scrollToBottom } = useScroll()
const { visible, clickBackBottom, throttleScrollMessageContainer } = useBackBottom(scrollToBottom) const { visible, clickBackBottom, throttleScrollContainer } = useBackBottom(scrollRef, scrollToBottom)
const isShowContinueQuestion = computed(() => { const isShowContinueQuestion = computed(() => {
return ( return (
...@@ -52,7 +52,7 @@ function handleScrollToBottom() { ...@@ -52,7 +52,7 @@ function handleScrollToBottom() {
</script> </script>
<template> <template>
<main ref="scrollRef" class="h-full overflow-y-auto overflow-x-hidden px-5" @scroll="throttleScrollMessageContainer"> <main ref="scrollRef" class="h-full overflow-y-auto overflow-x-hidden px-5" @scroll="throttleScrollContainer">
<div> <div>
<MessageItem <MessageItem
v-for="[key, messageItem] in messageList" v-for="[key, messageItem] in messageList"
......
...@@ -24,7 +24,7 @@ defineEmits<{ ...@@ -24,7 +24,7 @@ defineEmits<{
const { scrollRef, scrollToBottom } = useScroll() const { scrollRef, scrollToBottom } = useScroll()
const { visible, clickBackBottom, throttleScrollMessageContainer } = useBackBottom(scrollToBottom) const { visible, clickBackBottom, throttleScrollContainer } = useBackBottom(scrollRef, scrollToBottom)
const isShowContinueQuestion = computed(() => { const isShowContinueQuestion = computed(() => {
return ( return (
...@@ -54,7 +54,7 @@ function handleScrollToBottom() { ...@@ -54,7 +54,7 @@ function handleScrollToBottom() {
</script> </script>
<template> <template>
<main ref="scrollRef" class="h-full overflow-y-auto overflow-x-hidden px-5" @scroll="throttleScrollMessageContainer"> <main ref="scrollRef" class="h-full overflow-y-auto overflow-x-hidden px-5" @scroll="throttleScrollContainer">
<div> <div>
<MessageItem <MessageItem
v-for="[key, messageItem] in messageList" v-for="[key, messageItem] in messageList"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment