react-visjs-timeline修改配置项时垂直滚动自动跳至顶部问题
问题根因
在React项目中使用react-visjs-timeline组件时,只要传入组件的options配置项引用发生变化——无论修改的是movable属性还是其他任意配置——组件内部都会触发时间线实例的重绘逻辑,部分版本的组件甚至会直接重置可视区域状态、重建DOM结构,最终导致时间线的垂直滚动位置被强制重置到顶部,和具体修改的配置项无关。
可落地修复方案
- 缓存配置对象引用,避免无意义的更新
不要在组件函数作用域内直接写字面量形式的options对象传给Timeline组件(每次组件渲染都会生成新的对象引用,哪怕配置值完全没变化也会触发重绘),使用useMemo包裹配置对象,仅在实际依赖的配置值发生变化时才返回新的对象引用。// 仅当isScrollLocked变化时,才生成新的options引用 const options = useMemo(() => ({ width: '100%', height: '600px', movable: !isScrollLocked, // 其余固定配置项 }), [isScrollLocked]) - 配置更新前后手动保存、还原滚动位置
如果缓存引用后仍然存在滚动跳变问题,可以在修改配置前通过时间线实例拿到当前垂直滚动位置,等配置更新、组件重绘完成后,再手动把滚动位置设置回原有值:const timelineRef = useRef(null) const savedScrollTop = useRef(0) const handleToggleMovable = () => { // 切换配置前先记录当前滚动位置 if (timelineRef.current?.timeline) { savedScrollTop.current = timelineRef.current.timeline.getScrollTop() } setIsScrollLocked(prev => !prev) } // 配置更新完成后还原滚动位置 useEffect(() => { if (timelineRef.current?.timeline) { timelineRef.current.timeline.setScrollTop(savedScrollTop.current) } }, [isScrollLocked]) - 升级组件版本
较早版本的react-visjs-timeline存在已知缺陷:只要options引用变化就会直接销毁重建整个时间线DOM,必然导致滚动状态丢失,升级到最新稳定版本后,组件内部调用原生vis-timeline的setOptions方法做增量更新,不会全量重置DOM状态。
问题复现路径:先将时间线区域向下滚动,再点击切换水平滚动锁定状态的按钮,就会立刻观察到滚动位置跳回顶部的现象。
内容的提问来源于stack exchange,提问作者Naveed Ahmed
相关产品推荐
相关产品推荐

