diff --git a/packages/rax-scrollview/CHANGELOG.md b/packages/rax-scrollview/CHANGELOG.md index 42f0fa24..8ebdd971 100644 --- a/packages/rax-scrollview/CHANGELOG.md +++ b/packages/rax-scrollview/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 4.0.0 +- Remove `resetScroll` method +- Add `resetEndReached` method: reset status to trigger `onEndReached` +- Rename `onEndReachedThreshold`: `endReachedThreshold` + ## 3.6.1 - Fix `pixelRatio` is not initialized and make onEndReached can not triggered diff --git a/packages/rax-scrollview/README.md b/packages/rax-scrollview/README.md index a776f37e..a9bf3511 100644 --- a/packages/rax-scrollview/README.md +++ b/packages/rax-scrollview/README.md @@ -25,8 +25,8 @@ $ npm install rax-scrollview --save | scrollLeft | `number` | 0 | false | 横向滚动距离,优先级高于`scrollTo`方法(注:运行时小程序无法生效,请使用 `scrollTo` 方案) | miniApp wechatMiniprogrambytedanceMicroApp | | showsHorizontalScrollIndicator | `boolean` | true | false | 是否允许出现水平滚动条 | browser weex | | showsVerticalScrollIndicator | `boolean` | true | false | 是否允许出现垂直滚动条 | browser weex | -| onEndReachedThreshold | `number` | 500 | false | 设置加载更多的偏移 | browser weexminiApp wechatMiniprogrambytedanceMicroApp | -| onEndReached | `function` | - | false | 滚动区域还剩`onEndReachedThreshold`的长度时触发 | browser weexminiApp wechatMiniprogrambytedanceMicroAppquickApp | +| endReachedThreshold | `string/number` | 500rpx | false | 设置加载更多的偏移,推荐使用 string 类型来定义 | browser weexminiApp wechatMiniprogrambytedanceMicroApp | +| onEndReached | `function` | - | false | 滚动区域还剩`onEndReachedThreshold`的长度时触发, 默认只触发一次,若想触发多次,需配合 resetEndReached 方法使用 | browser weexminiApp wechatMiniprogrambytedanceMicroAppquickApp | | onScroll | `function` | - | false | 滚动时触发的事件,返回当前滚动的水平垂直距离 | browser weexminiApp wechatMiniprogrambytedanceMicroApp quickApp| | onTouchStart | `function` | - | false | touchStart 触发的事件,返回触摸点数据(touches、changedTouches) | browser weexminiApp | | onTouchMove | `function` | - | false | touchMove 触发的事件,返回触摸点数据(touches、changedTouches) | browser weexminiApp | @@ -36,7 +36,7 @@ $ npm install rax-scrollview --save ## 方法 -### scrollTo({x: number,y: number, animated?: boolean, duration?: number}) +### scrollTo({x: string|number,y: string|number, animated?: boolean, duration?: number}) #### 参数 @@ -44,8 +44,8 @@ $ npm install rax-scrollview --save | **属性** | **类型** | **默认值** | **必填** | **描述** | **支持** | | -------- | --------- | ---------- | -------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| x | `number` | - | 否 |  横向的偏移量 | browser weexminiApp wechatMiniprogrambytedanceMicroApp | -| y | `number` | - | 否 | 纵向的偏移量 | browser weexminiApp wechatMiniprogrambytedanceMicroApp | +| x | `string/number` | - | 否 |  横向的偏移, 推荐使用 string 类型量 | browser weexminiApp wechatMiniprogrambytedanceMicroApp | +| y | `string/number` | - | 否 | 纵向的偏移,推荐使用 string 类型量 | browser weexminiApp wechatMiniprogrambytedanceMicroApp | | animated | `boolean` | `true` | 否 | 在设置滚动条位置时使用动画过渡 | browser weexminiApp wechatMiniprogrambytedanceMicroApp | | duration | `number` | 400 | 否 | 当 `animated` 设置为 `true` 时,可以设置 duration 来控制动画的执行时间,单位 `ms` | browser miniApp wechatMiniprogrambytedanceMicroApp | @@ -61,6 +61,10 @@ $ npm install rax-scrollview --save | animated | `boolean` | `true` | 否 | 在设置滚动条位置时使用动画过渡 | weexminiApp wechatMiniprogrambytedanceMicroApp | | duration | `number` | 400 | 否 | 当 `animated` 设置为 `true` 时,可以设置 duration 来控制动画的执行时间,单位 `ms` | miniApp wechatMiniprogram bytedanceMicroApp | +### resetEndReached() + +表示重置触底状态,当且仅当第一次触底或调用 `resetEndReached()` 后的第一次触底才会触发 `onEndReached` 函数 + ## 示例 ```jsx @@ -112,7 +116,7 @@ class App extends Component { { - this.horizontalScrollView.current.scrollTo({ x: 0 }); + this.horizontalScrollView.current.scrollTo({ x: '0rpx' }); }} > Scroll to start @@ -148,7 +152,7 @@ class App extends Component { { - this.scrollView.scrollTo({ y: 0 }); + this.scrollView.scrollTo({ y: '0rpx' }); }} > Scroll to top @@ -195,7 +199,7 @@ const styles = { }, eventLogBox: { padding: '10rpx', - margin: '10rpx;, + margin: '10rpx'; height: '80rpx', borderWidth: '1rpx', borderColor: '#f0f0f0', diff --git a/packages/rax-scrollview/package.json b/packages/rax-scrollview/package.json index e5259ddc..063c9483 100644 --- a/packages/rax-scrollview/package.json +++ b/packages/rax-scrollview/package.json @@ -1,6 +1,6 @@ { "name": "rax-scrollview", - "version": "3.6.1", + "version": "4.0.0", "description": "ScrollView component for Rax.", "license": "BSD-3-Clause", "main": "lib/index.js", diff --git a/packages/rax-scrollview/src/miniapp/index.tsx b/packages/rax-scrollview/src/miniapp/index.tsx index 01ff0038..d52e552d 100644 --- a/packages/rax-scrollview/src/miniapp/index.tsx +++ b/packages/rax-scrollview/src/miniapp/index.tsx @@ -33,14 +33,14 @@ function translateToPx(origin: string | number): number { const matched = /^(\d+)(r{0,1}px){0,1}$/.exec(origin); if (matched) { if (!matched[2]) { - return parseInt(matched[1]); + return parseInt(matched[1], 10); } if (matched[2] === 'rpx') { const pixelRatio = getPixelRatio(); - return parseInt(matched[1]) * pixelRatio; + return parseInt(matched[1], 10) * pixelRatio; } if (matched[2] === 'px') { - return parseInt(matched[1]); + return parseInt(matched[1], 10); } } return 0; @@ -56,7 +56,7 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( onScroll, children, disableScroll = false, - onEndReachedThreshold + endReachedThreshold } = props; const [scrollTop] = useState(0); const [scrollLeft] = useState(0); @@ -64,6 +64,7 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( const [scrollAnimationDuration, setScrollAnimationDuration] = useState(ANIMATION_DURATION); const [scrollIntoViewId] = useState(null); const scrollerRef = useRef(null); + const endReachedStatus = useRef(false); const handleScroll = e => { if (onScroll) { e.nativeEvent = { @@ -83,14 +84,16 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( onScroll(e); } }; + const handleEndReached = (e) => { + if (onEndReached && !endReachedStatus.current) { + endReachedStatus.current = true; + onEndReached(e); + } + }; useImperativeHandle(ref, () => ({ _nativeNode: scrollerRef.current, - resetScroll() { - if (horizontal) { - scrollerRef.current.setAttribute('scroll-left', '0'); - } else { - scrollerRef.current.setAttribute('scroll-top', '0'); - } + resetEndReached() { + endReachedStatus.current = false; }, scrollTo(options?: { x?: number | string; @@ -138,7 +141,7 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( className ); - const endReachedThreshold = translateToPx(onEndReachedThreshold); + const transedEndReachedThreshold = translateToPx(endReachedThreshold); return ( = forwardRef( scroll-top={scrollTop} scroll-left={scrollLeft} onScroll={onScroll ? handleScroll : null} - onScrollToLower={onEndReached} - lower-threshold={endReachedThreshold} + onScrollToLower={onEndReached ? handleEndReached : null} + lower-threshold={transedEndReachedThreshold} scroll-with-animation={scrollWithAnimation} scroll-animation-duration={scrollAnimationDuration} scroll-x={!disableScroll && horizontal} diff --git a/packages/rax-scrollview/src/types.ts b/packages/rax-scrollview/src/types.ts index c9401b77..2fe9b6b7 100644 --- a/packages/rax-scrollview/src/types.ts +++ b/packages/rax-scrollview/src/types.ts @@ -2,7 +2,7 @@ import { RefAttributes, HTMLAttributes, UIEvent } from 'rax'; export interface ScrollViewRefObject { _nativeNode: HTMLDivElement; - resetScroll: () => void; + resetEndReached: () => void; scrollTo: (options?: { x?: number | string; y?: number | string; @@ -26,7 +26,7 @@ export interface ScrollViewProps extends RefAttributes, HTM horizontal?: boolean; showsHorizontalScrollIndicator?: boolean; showsVerticalScrollIndicator?: boolean; - onEndReachedThreshold?: number | string; + endReachedThreshold?: number | string; onEndReached?: (e: ScrollEvent) => void; onScroll?: (e: ScrollEvent) => void; } diff --git a/packages/rax-scrollview/src/utils/wrapDefaultProperties.ts b/packages/rax-scrollview/src/utils/wrapDefaultProperties.ts index 6af2866c..f724e76c 100644 --- a/packages/rax-scrollview/src/utils/wrapDefaultProperties.ts +++ b/packages/rax-scrollview/src/utils/wrapDefaultProperties.ts @@ -1,13 +1,13 @@ import { ForwardRefExoticComponent } from 'rax'; import { ScrollViewProps } from '../types'; -const DEFAULT_END_REACHED_THRESHOLD = 500; +const DEFAULT_END_REACHED_THRESHOLD = '500rpx'; const DEFAULT_SCROLL_CALLBACK_THROTTLE = 50; export default function wrapDefaultProperties(ScrollView: ForwardRefExoticComponent): ForwardRefExoticComponent { ScrollView.defaultProps = { scrollEventThrottle: DEFAULT_SCROLL_CALLBACK_THROTTLE, - onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD, + endReachedThreshold: DEFAULT_END_REACHED_THRESHOLD, showsHorizontalScrollIndicator: true, showsVerticalScrollIndicator: true, className: 'rax-scrollview' diff --git a/packages/rax-scrollview/src/web/index.tsx b/packages/rax-scrollview/src/web/index.tsx index 3a966776..34fe5c53 100644 --- a/packages/rax-scrollview/src/web/index.tsx +++ b/packages/rax-scrollview/src/web/index.tsx @@ -76,13 +76,13 @@ function translateToPx(origin: string | number): number { const matched = /^(\d+)(r{0,1}px){0,1}$/.exec(origin); if (matched) { if (!matched[2]) { - return parseInt(matched[1]) * pixelRatio; + return parseInt(matched[1], 10) * pixelRatio; } if (matched[2] === 'rpx') { - return parseInt(matched[1]) * pixelRatio; + return parseInt(matched[1], 10) * pixelRatio; } if (matched[2] === 'px') { - return parseInt(matched[1]); + return parseInt(matched[1], 10); } } return 0; @@ -100,13 +100,12 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( showsHorizontalScrollIndicator, showsVerticalScrollIndicator, onEndReached, - onEndReachedThreshold, + endReachedThreshold, onScroll, children } = props; const lastScrollDistance = useRef(0); - const lastScrollContentSize = useRef(0); - const scrollerNodeSize = useRef(0); + const endReachedStatus = useRef(false); const scrollerRef = useRef(null); const contentContainerRef = useRef(null); const handleScroll = e => { @@ -130,7 +129,7 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( if (onEndReached) { const scrollerNode = scrollerRef.current; - scrollerNodeSize.current = horizontal + const scrollerNodeSize = horizontal ? scrollerNode.offsetWidth : scrollerNode.offsetHeight; // NOTE:in iOS7/8 offsetHeight/Width is is inaccurate ( use scrollHeight/Width ) @@ -141,18 +140,16 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( ? scrollerNode.scrollLeft : scrollerNode.scrollTop; - const endReachedThreshold = translateToPx(onEndReachedThreshold); + const transedEndReachedThreshold = translateToPx(endReachedThreshold); const isEndReached = - scrollContentSize - scrollDistance - scrollerNodeSize.current < - endReachedThreshold; + scrollContentSize - scrollDistance - scrollerNodeSize < + transedEndReachedThreshold; const isScrollToEnd = scrollDistance > lastScrollDistance.current; - const isLoadedMoreContent = - scrollContentSize != lastScrollContentSize.current; - if (isEndReached && isScrollToEnd && isLoadedMoreContent) { - lastScrollContentSize.current = scrollContentSize; + if (isEndReached && isScrollToEnd && !endReachedStatus.current) { + endReachedStatus.current = true; props.onEndReached(e); } @@ -161,9 +158,8 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( }; useImperativeHandle(ref, () => ({ _nativeNode: scrollerRef.current, - resetScroll() { - lastScrollContentSize.current = 0; - lastScrollDistance.current = 0; + resetEndReached() { + endReachedStatus.current = false; }, scrollTo(options?: { x?: number | string; @@ -262,7 +258,7 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( const webProps = { ...props }; - delete webProps.onEndReachedThreshold; + delete webProps.endReachedThreshold; return ( = forwardRef( (props, ref) => { let { @@ -27,11 +37,10 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( showsHorizontalScrollIndicator, showsVerticalScrollIndicator, onEndReached, - onEndReachedThreshold, + endReachedThreshold, onScroll, children } = props; - const [loadmoreretry, setLoadmoreretry] = useState(0); const scrollerRef = useRef(null); const contentContainerRef = useRef(null); const handleScroll = e => { @@ -52,8 +61,9 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( }; useImperativeHandle(ref, () => ({ _nativeNode: scrollerRef.current, - resetScroll() { - setLoadmoreretry(loadmoreretry + 1); + resetEndReached() { + // @ts-ignore + scrollerRef.current.resetLoadmore(); }, scrollTo(options?: { x?: number; @@ -95,10 +105,8 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( })); // In weex must be int value - onEndReachedThreshold = - typeof onEndReachedThreshold === 'string' - ? parseInt(onEndReachedThreshold, 10) - : onEndReachedThreshold; + const transedEndReachedThreshold = translateToPx(endReachedThreshold); + if (style) { const childLayoutProps = ['alignItems', 'justifyContent'].filter( prop => style[prop] !== undefined @@ -169,8 +177,7 @@ const ScrollView: ForwardRefExoticComponent = forwardRef( showScrollbar={showsScrollIndicator} onLoadmore={onEndReached} onScroll={onScroll ? handleScroll : null} - loadmoreoffset={onEndReachedThreshold} - loadmoreretry={loadmoreretry} + loadmoreoffset={transedEndReachedThreshold} scrollDirection={horizontal ? 'horizontal' : 'vertical'} > {refreshContainer}