fix: scroll error
parent
0de3e6b716
commit
c579bb0ad5
|
@ -3,12 +3,11 @@ import Item from './Item';
|
||||||
import ScrollBar from './ScrollBar';
|
import ScrollBar from './ScrollBar';
|
||||||
import useHeights from './hooks/useHeights';
|
import useHeights from './hooks/useHeights';
|
||||||
import useScrollTo from './hooks/useScrollTo';
|
import useScrollTo from './hooks/useScrollTo';
|
||||||
// import useDiffItem from './hooks/useDiffItem';
|
|
||||||
import useFrameWheel from './hooks/useFrameWheel';
|
import useFrameWheel from './hooks/useFrameWheel';
|
||||||
import useMobileTouchMove from './hooks/useMobileTouchMove';
|
import useMobileTouchMove from './hooks/useMobileTouchMove';
|
||||||
import useOriginScroll from './hooks/useOriginScroll';
|
import useOriginScroll from './hooks/useOriginScroll';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import { computed, nextTick, reactive, ref, watchEffect } from 'vue';
|
import { computed, nextTick, reactive, watchEffect } from 'vue';
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
import createRef from '../_util/createRef';
|
import createRef from '../_util/createRef';
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ const ListProps = {
|
||||||
height: PropTypes.number,
|
height: PropTypes.number,
|
||||||
itemHeight: PropTypes.number,
|
itemHeight: PropTypes.number,
|
||||||
/** If not match virtual scroll condition, Set List still use height of container. */
|
/** If not match virtual scroll condition, Set List still use height of container. */
|
||||||
fullHeight: PropTypes.bool,
|
fullHeight: PropTypes.bool.def(true),
|
||||||
itemKey: PropTypes.any,
|
itemKey: PropTypes.any,
|
||||||
component: PropTypes.any,
|
component: PropTypes.any,
|
||||||
/** Set `false` will always use real scroll instead of virtual one */
|
/** Set `false` will always use real scroll instead of virtual one */
|
||||||
|
@ -92,17 +91,12 @@ const List = {
|
||||||
|
|
||||||
const alignedTop = keepInRange(value);
|
const alignedTop = keepInRange(value);
|
||||||
|
|
||||||
|
if (componentRef.current) {
|
||||||
componentRef.current.scrollTop = alignedTop;
|
componentRef.current.scrollTop = alignedTop;
|
||||||
state.scrollTop = alignedTop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================ Legacy ================================
|
state.scrollTop = alignedTop;
|
||||||
// Put ref here since the range is generate by follow
|
}
|
||||||
const rangeRef = ref({ start: 0, end: state.mergedData.length });
|
|
||||||
|
|
||||||
// const diffItemRef = ref();
|
|
||||||
// const [diffItem] = useDiffItem(mergedData, getKey);
|
|
||||||
// diffItemRef.current = diffItem;
|
|
||||||
|
|
||||||
// ================================ Height ================================
|
// ================================ Height ================================
|
||||||
const [setInstance, collectHeight, heights] = useHeights(getKey, null, null);
|
const [setInstance, collectHeight, heights] = useHeights(getKey, null, null);
|
||||||
|
@ -130,7 +124,6 @@ const List = {
|
||||||
const currentItemBottom =
|
const currentItemBottom =
|
||||||
itemTop + (cacheHeight === undefined ? props.itemHeight : cacheHeight);
|
itemTop + (cacheHeight === undefined ? props.itemHeight : cacheHeight);
|
||||||
|
|
||||||
// Check item top in the range
|
|
||||||
if (currentItemBottom >= state.scrollTop && startIndex === undefined) {
|
if (currentItemBottom >= state.scrollTop && startIndex === undefined) {
|
||||||
startIndex = i;
|
startIndex = i;
|
||||||
startOffset = itemTop;
|
startOffset = itemTop;
|
||||||
|
@ -156,8 +149,6 @@ const List = {
|
||||||
|
|
||||||
// Give cache to improve scroll experience
|
// Give cache to improve scroll experience
|
||||||
endIndex = Math.min(endIndex + 1, state.mergedData.length);
|
endIndex = Math.min(endIndex + 1, state.mergedData.length);
|
||||||
rangeRef.value.start = startIndex;
|
|
||||||
rangeRef.value.end = endIndex;
|
|
||||||
return {
|
return {
|
||||||
scrollHeight: itemTop,
|
scrollHeight: itemTop,
|
||||||
start: startIndex,
|
start: startIndex,
|
||||||
|
@ -166,7 +157,7 @@ const List = {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
// =============================== In Range ===============================
|
// =============================== In Range ===============================
|
||||||
const maxScrollHeight = computed(() => calRes.scrollHeight - props.height);
|
const maxScrollHeight = computed(() => calRes.value.scrollHeight - props.height);
|
||||||
|
|
||||||
function keepInRange(newScrollTop) {
|
function keepInRange(newScrollTop) {
|
||||||
let newTop = Math.max(newScrollTop, 0);
|
let newTop = Math.max(newScrollTop, 0);
|
||||||
|
@ -223,29 +214,29 @@ const List = {
|
||||||
});
|
});
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
componentRef.current.removeEventListener('wheel', onRawWheel);
|
if (componentRef.current) {
|
||||||
componentRef.current.removeEventListener('DOMMouseScroll', onFireFoxScroll);
|
|
||||||
componentRef.current.removeEventListener('MozMousePixelScroll', onMozMousePixelScroll);
|
|
||||||
|
|
||||||
// Firefox only
|
// Firefox only
|
||||||
function onMozMousePixelScroll(e) {
|
function onMozMousePixelScroll(e) {
|
||||||
if (inVirtual.value) {
|
if (inVirtual.value) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
componentRef.current.removeEventListener('wheel', onRawWheel);
|
||||||
|
componentRef.current.removeEventListener('DOMMouseScroll', onFireFoxScroll);
|
||||||
|
componentRef.current.removeEventListener('MozMousePixelScroll', onMozMousePixelScroll);
|
||||||
componentRef.current.addEventListener('wheel', onRawWheel);
|
componentRef.current.addEventListener('wheel', onRawWheel);
|
||||||
componentRef.current.addEventListener('DOMMouseScroll', onFireFoxScroll);
|
componentRef.current.addEventListener('DOMMouseScroll', onFireFoxScroll);
|
||||||
componentRef.current.addEventListener('MozMousePixelScroll', onMozMousePixelScroll);
|
componentRef.current.addEventListener('MozMousePixelScroll', onMozMousePixelScroll);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ================================= Ref ==================================
|
// ================================= Ref ==================================
|
||||||
const scrollTo = useScrollTo(
|
const scrollTo = useScrollTo(
|
||||||
componentRef,
|
componentRef,
|
||||||
state.mergedData,
|
state,
|
||||||
heights,
|
heights,
|
||||||
props.itemHeight,
|
props,
|
||||||
getKey,
|
getKey,
|
||||||
collectHeight,
|
collectHeight,
|
||||||
syncScrollTop,
|
syncScrollTop,
|
||||||
|
@ -288,7 +279,7 @@ const List = {
|
||||||
height,
|
height,
|
||||||
itemHeight,
|
itemHeight,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
fullHeight = true,
|
fullHeight,
|
||||||
data,
|
data,
|
||||||
itemKey,
|
itemKey,
|
||||||
virtual,
|
virtual,
|
||||||
|
|
|
@ -76,8 +76,10 @@ export default {
|
||||||
delayHidden() {
|
delayHidden() {
|
||||||
clearTimeout(this.visibleTimeout);
|
clearTimeout(this.visibleTimeout);
|
||||||
this.state.visible = true;
|
this.state.visible = true;
|
||||||
|
|
||||||
this.visibleTimeout = setTimeout(() => {
|
this.visibleTimeout = setTimeout(() => {
|
||||||
this.state.visible = false;
|
this.state.visible = false;
|
||||||
|
this.$forceUpdate(); // why ?
|
||||||
}, 2000);
|
}, 2000);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -191,7 +193,6 @@ export default {
|
||||||
const { prefixCls } = this.$props;
|
const { prefixCls } = this.$props;
|
||||||
const spinHeight = this.getSpinHeight() + 'px';
|
const spinHeight = this.getSpinHeight() + 'px';
|
||||||
const top = this.getTop() + 'px';
|
const top = this.getTop() + 'px';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={this.scrollbarRef}
|
ref={this.scrollbarRef}
|
||||||
|
@ -202,7 +203,7 @@ export default {
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
// display: visible ? null : 'none',
|
display: visible ? null : 'none',
|
||||||
}}
|
}}
|
||||||
onMousedown={this.onContainerMouseDown}
|
onMousedown={this.onContainerMouseDown}
|
||||||
onMousemove={this.delayHidden}
|
onMousemove={this.delayHidden}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
import { ref, toRaw, watch } from 'vue';
|
|
||||||
import cloneDeep from 'lodash-es/cloneDeep';
|
|
||||||
import { findListDiffIndex } from '../utils/algorithmUtil';
|
|
||||||
|
|
||||||
export default function useDiffItem(data, getKey, onDiff) {
|
|
||||||
const diffItem = ref(null);
|
|
||||||
let prevData = cloneDeep(toRaw(data));
|
|
||||||
watch(data, val => {
|
|
||||||
const diff = findListDiffIndex(prevData || [], val || [], getKey);
|
|
||||||
if (diff?.index !== undefined) {
|
|
||||||
onDiff?.(diff.index);
|
|
||||||
diffItem = val[diff.index];
|
|
||||||
}
|
|
||||||
prevData = cloneDeep(toRaw(val));
|
|
||||||
});
|
|
||||||
|
|
||||||
return [diffItem];
|
|
||||||
}
|
|
|
@ -61,14 +61,11 @@ export default function useMobileTouchMove(inVirtual, listRef, callback) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
watch(inVirtual, val => {
|
watch(inVirtual, val => {
|
||||||
if (val.value) {
|
|
||||||
listRef.current.addEventListener('touchstart', onTouchStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
listRef.current.removeEventListener('touchstart', onTouchStart);
|
listRef.current.removeEventListener('touchstart', onTouchStart);
|
||||||
cleanUpEvents();
|
cleanUpEvents();
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
};
|
if (val.value) {
|
||||||
|
listRef.current.addEventListener('touchstart', onTouchStart);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { reactive } from 'vue';
|
|
||||||
|
|
||||||
export default (isScrollAtTop, isScrollAtBottom) => {
|
export default (isScrollAtTop, isScrollAtBottom) => {
|
||||||
// Do lock for a wheel when scrolling
|
// Do lock for a wheel when scrolling
|
||||||
let lock = false;
|
let lock = false;
|
||||||
|
@ -13,21 +11,12 @@ export default (isScrollAtTop, isScrollAtBottom) => {
|
||||||
lock = false;
|
lock = false;
|
||||||
}, 50);
|
}, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass to ref since global add is in closure
|
|
||||||
const scrollPingRef = reactive({
|
|
||||||
top: isScrollAtTop.value,
|
|
||||||
bottom: isScrollAtBottom.value,
|
|
||||||
});
|
|
||||||
// scrollPingRef.value.top = isScrollAtTop;
|
|
||||||
// scrollPingRef.value.bottom = isScrollAtBottom;
|
|
||||||
|
|
||||||
return (deltaY, smoothOffset = false) => {
|
return (deltaY, smoothOffset = false) => {
|
||||||
const originScroll =
|
const originScroll =
|
||||||
// Pass origin wheel when on the top
|
// Pass origin wheel when on the top
|
||||||
(deltaY < 0 && scrollPingRef.top) ||
|
(deltaY < 0 && isScrollAtTop.value) ||
|
||||||
// Pass origin wheel when on the bottom
|
// Pass origin wheel when on the bottom
|
||||||
(deltaY > 0 && scrollPingRef.bottom);
|
(deltaY > 0 && isScrollAtBottom.value);
|
||||||
|
|
||||||
if (smoothOffset && originScroll) {
|
if (smoothOffset && originScroll) {
|
||||||
// No need lock anymore when it's smooth offset from touchMove interval
|
// No need lock anymore when it's smooth offset from touchMove interval
|
||||||
|
|
|
@ -4,9 +4,9 @@ import raf from '../../_util/raf';
|
||||||
|
|
||||||
export default function useScrollTo(
|
export default function useScrollTo(
|
||||||
containerRef,
|
containerRef,
|
||||||
data,
|
state,
|
||||||
heights,
|
heights,
|
||||||
itemHeight,
|
props,
|
||||||
getKey,
|
getKey,
|
||||||
collectHeight,
|
collectHeight,
|
||||||
syncScrollTop,
|
syncScrollTop,
|
||||||
|
@ -15,7 +15,8 @@ export default function useScrollTo(
|
||||||
|
|
||||||
return arg => {
|
return arg => {
|
||||||
raf.cancel(scroll);
|
raf.cancel(scroll);
|
||||||
|
const data = state.mergedData;
|
||||||
|
const itemHeight = props.itemHeight;
|
||||||
if (typeof arg === 'number') {
|
if (typeof arg === 'number') {
|
||||||
syncScrollTop(arg);
|
syncScrollTop(arg);
|
||||||
} else if (arg && typeof arg === 'object') {
|
} else if (arg && typeof arg === 'object') {
|
||||||
|
|
Loading…
Reference in New Issue