<div id="position"><div>这是可滚动元素</div></div>
以下都在 id 为 position 上取值:
期间将 PullToRefresh 组件进行重构为 hooks, 伪代码如下:
function PullToRefresh(props: PullToRefreshProps) {...useEffect(() => {addEventListener()return () => {removeEventListener()}}, [useBodyScroll])const addEventListener = () => {if (useBodyScroll) {window.addEventListener('scroll', scroll)} else {scrollViewRef.current?.addEventListener('scroll', scroll)}}const removeEventListener = () => {if (useBodyScroll) {window.removeEventListener('scroll', scroll)} else {scrollViewRef.current?.removeEventListener('scroll', scroll)}}...return (<div className={classStr} ref={scrollViewRef} style={containStyle} id={id}>{useBodyScroll ? (children) : (<div className={`${prefixCls}-content`} style={{ minWidth: '100%', ...contentStyle }}>{children}</div>)}{refreshing ? <div className={`${prefixCls}-loading`}>{loadingInfo}</div> : null}</div>)}export default PullToRefresh
踩的坑点是, 当使用方进行如下使用时, setList(newArr) 没有生效。目前归因是由于 hooks 的闭包原因, 在 window 上订阅的事件中使用的值每次执行没法获取最新的值。目前推荐还是使用 class 来构造此类组件。
export default function PullToRefreshDemo() {const getMockData = () => {let mockList: React.ReactNode[] = []for (let i = 0; i < 40; i++) {mockList.push(<p key={i}>这是标签这是标签</p>)}return mockList}const [list, setList] = useState(getMockData())const [refreshing, setRefreshing] = useState(true)const [checked, setChecked] = useState(false)useEffect(() => {setRefreshing(false)}, [])useEffect(() => {setList(getMockData())}, [checked])const onLoad = (_direction: string, done: () => void) => {console.log('请求接口')setRefreshing(true)const newArr = list.slice()setTimeout(() => {for (let i = 0; i < 5; i++) {newArr.push(<p key={Math.floor(100000000 * Math.random())} style={{ color: 'red' }}>这是新的标签</p>)}setList(newArr)setRefreshing(false)done()}, 1000)}const partlyScrollStyle: React.CSSProperties = {display: 'flex',flexDirection: 'column',height: '100%',overflow: 'auto'}return (<div style={checked ? {} : partlyScrollStyle}><div><label>是否开启全局滚动</label>: <Switch checked={checked} onChange={() => setChecked(!checked)} /></div><Head title={checked ? '全局滚动' : '局部滚动'} /><PullToRefresh onLoad={onLoad} refreshing={refreshing} useBodyScroll={checked}>{list}</PullToRefresh></div>)}
见 JEST 测试一节。