diff --git a/src/hooks/useAutoScroll.ts b/src/hooks/useAutoScroll.ts
new file mode 100644
index 0000000..4bed007
--- /dev/null
+++ b/src/hooks/useAutoScroll.ts
@@ -0,0 +1,124 @@
+import { ref, onMounted, onUnmounted } from 'vue';
+
+/**
+@example
+1. 页面引入该hooks, 并调用useAutoScroll(),返回三个值:canAutoScroll, contentRef, contentScrollFN
+import { useAutoScroll } from '@/hooks/useAutoScroll';
+const { canAutoScroll, contentRef, contentScrollFN } = useAutoScroll();
+
+2. 需要配置自动滚动的dom加上contentRef属性(contentRef名称不能修改,必须匹配),并监听scroll调用contentScrollFN()方法
+
+
+
+3. 在请求流式数据时,设置canAutoScroll为true
+
+### 注意事项
+滚动的dom样式要求
+.wordbox {
+ overflow-y: auto;
+ overflow-x: hidden;
+ scrollbar-width: none;
+ word-break: break-all;
+}
+.wordbox::-webkit-scrollbar {
+ display: none;
+}
+ */
+export function useAutoScroll() {
+ let prescrollHeight = 0;
+ let touchStartPointY = 0;
+ const canAutoScroll = ref(false);
+ const contentRef = ref(null);
+
+ const contentScrollFN = () => {
+ if (canAutoScroll.value === true) {
+ return;
+ }
+ // +10 这里是一个缓冲区,只要快到底部就触发自动滚动
+ if (contentRef.value.scrollTop + contentRef.value.clientHeight + 10 >= contentRef.value.scrollHeight) {
+ console.log('设置开始自动滚动');
+ canAutoScroll.value = true;
+ }
+ };
+
+ const observeScrollFN = () => {
+ const observe = new MutationObserver((mutations) => {
+ if (!contentRef.value || !canAutoScroll.value) {
+ return;
+ }
+ mutations.forEach((mutation) => {
+ if (mutation.type !== 'childList') {
+ return;
+ }
+
+ if (prescrollHeight != contentRef.value.scrollHeight) {
+ contentRef.value.scrollTo({
+ top: contentRef.value.scrollHeight,
+ behavior: 'smooth',
+ });
+ prescrollHeight = contentRef.value.scrollHeight;
+ }
+ });
+ });
+
+ const config = {
+ childList: true,
+ subtree: true,
+ };
+ observe.observe(contentRef.value, config);
+ };
+
+ const touchstartFN = (event) => {
+ touchStartPointY = event.targetTouches[0].pageY;
+ };
+
+ const touchmoveFN = (event) => {
+ if (event.targetTouches.length > 1) {
+ return;
+ }
+ // event.targetTouches[0].pageY - touchStartPointY > 0 即为内容往上滑动
+ // 5这里也是缓冲区
+ if (canAutoScroll.value === true && event.targetTouches[0].pageY - touchStartPointY > 5) {
+ canAutoScroll.value = false;
+ }
+ };
+
+ const touchendFN = () => {
+ touchStartPointY = 0;
+ };
+
+ const wheelFN = (event) => {
+ /** 修复mac下whell触发后惯性继续触发问题 */
+ if (event.deltaY < 0) {
+ // console.log('向上滚动');
+ canAutoScroll.value = false;
+ } else if (event.deltaY > 0) {
+ // console.log('向下滚动');
+ }
+ };
+
+ onMounted(() => {
+ observeScrollFN();
+ window.addEventListener('touchstart', touchstartFN);
+ window.addEventListener('touchmove', touchmoveFN);
+ window.addEventListener('touchend', touchendFN);
+ window.addEventListener('wheel', wheelFN);
+ });
+
+ onUnmounted(() => {
+ window.removeEventListener('touchstart', touchstartFN);
+ window.removeEventListener('touchmove', touchmoveFN);
+ window.removeEventListener('touchend', touchendFN);
+ window.removeEventListener('wheel', wheelFN);
+ });
+
+ return {
+ canAutoScroll,
+ contentRef,
+ contentScrollFN,
+ };
+}
diff --git a/src/views/demo/sseFetch.vue b/src/views/demo/sseFetch.vue
index a6e3e65..537a3b9 100644
--- a/src/views/demo/sseFetch.vue
+++ b/src/views/demo/sseFetch.vue
@@ -15,40 +15,37 @@
-
+ >