Closed CJY0208 closed 5 years ago
@CJY0208 这是因为每次移动 DOM 的时候,都会自动重置滚动条高度,Vue 的 <keep-alive>
组件也是如此的。可以看下这个例子 Control cache 手动修改滚动条。
OK,了解了,可否尝试将保存滚动位置的行为纳入到 KeepAlive 中?例如
<KeepAlive>
{({ saveScrollTop }) => (
<Comp ref={comp => {
saveScrollTop(comp.scrollContainer)
}} />
)}
</KeepAlive>
或者将 saveScrollTop
行为注入到 Comp props
中
@CJY0208 好问题,原先我也有考虑过。不过考虑到用户在一个组件中可能会有多个想要保存的滚动条位置,因此没有在库中做这些操作。
如果有多个滚动容器的话,可考虑 saveScrollTop
注入 Comp props
并允许调用多次
在组件被缓存时将所有订阅了 saveScrollTop
需求的容器 scrollTop
记住,并于组件恢复时恢复各订阅容器的 scrollTop
,感觉会是一个不错的功能
@CJY0208 这个功能我觉得通过 bindLifecycle
这个高阶函数绑定组件,然后在组件的生命周期里自己设置保存的滚动值会好一些。
@bindLifecycle
class List extends React.Component {
static defaultProps = {
onMount: () => {}
};
listScrollTop = 0;
componentDidMount() {
console.log("componentDidMount");
const { setControlDisabled } = this.props;
// 5. Disabled for each mount component
setControlDisabled("List", true);
setTimeout(() => {
document.querySelector("#root").scrollTop = this.listScrollTop;
});
}
componentWillUnmount() {
console.log("componentWillUnmount");
}
handleEnterDetails = () => {
const { setControlDisabled } = this.props;
// 6. Need to keep the cache after going to the next page
setControlDisabled("List", false);
this.listScrollTop = document.querySelector("#root").scrollTop;
};
render() {
return (
<div className="list-wrapper">
<h1>This is list</h1>
<p>
<Link to="/">Back to home</Link>
</p>
<div className="list">
{new Array(20).fill(null).map((v, index) => (
<div className="list-item">
This is <span style={{ color: "#f00" }}>{index}</span>
<Content />
<br />
<Link to="/details" onClick={this.handleEnterDetails}>
Click to enter details
</Link>
</div>
))}
</div>
</div>
);
}
}
在 react-router-cache-route 中,通过生命周期应该也能轻易实现这个功能。
import React, { Component } from 'react'
export default class List extends Component {
constructor(props, ...args) {
super(props, ...args)
props.cacheLifecycles.didCache(this.componentDidCache)
props.cacheLifecycles.didRecover(this.componentDidRecover)
}
componentDidCache = () => {
console.log('List cached')
}
componentDidRecover = () => {
console.log('List recovered')
}
render() {
return (
// ...
)
}
}
测试时发现这个情况
使用
<KeepAlive />
包裹长列表组件后,列表滚动至底部并触发keep-alive
,缓存恢复时,长列表的scrollTop
恢复为0
猜测和
createPortal
工作方式有关,或者是不是我的使用方式有误?