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,
};
}