LitElement:在重新渲染期间保持滚动位置

问题描述

伙计们!

我有一个仪表板应用程序,其中包含一个或多或少长的页面。在页面的末尾,有一个显示一些数据的网格容器。在此容器内,用户可以在此容器的不同视图之间切换,然后更改 property_activeAlarmsListViewSet,可以是 listtop)。

视图之间的切换工作正常,正如预期的那样,我唯一遇到的是,页面在渲染过程中跳转到顶部。

我已经尝试捕捉 update() 调用并自己处理它(是的,不再跳转),但也没有更多的视图切换,因为没有重新渲染发生:

update(changedProperties) {
  if (changedProperties.has('_activeAlarmsListViewSet') && changedProperties.get('_activeAlarmsListViewSet') != null) {
    console.log('No re-render');
  } else {
    super.update(changedProperties);
  }
}

是否有可能在不“跳转”到页面顶部并保持滚动位置的情况下触发重新渲染?

谢谢!

解决方法

我不认为问题出在 LitElement - 当 render 仅被调用更新已更改的部分时,DOM 的其余部分保持不变,只要内容很高,您滚动到的任何位置都会保持不变够了。

我认为问题在于您在 listtop 状态之间有一个重排,高度较短,以便浏览器将滚动更正到中间最大高度.

我最常在加载器和异步指令中看到这一点,因为它们在等待 Promise 时替换了 DOM。

例如:

render() {
    return html`... ${until(getAndRenderData(),'loading...')}`;
}

将导致加载数据的 DOM 被替换为 loading... 每次发生任何更新,而我们只希望它发生在 getAndRenderData() 可能更改时。

有几种方法可以解决这个问题,但最简单的方法可能是使用 guard 指令:

render() {
    return html`... ${guard(this._activeAlarmsListViewSet,() => until(getAndRenderData(this._activeAlarmsListViewSet),'loading...'))}`;
}

现在 guard 中的内容仅在 this._activeAlarmsListViewSet 更改时才会更改,您不必阻止 update 调用。

我发现的另一种方法是将您的 listtop 视图拆分为具有内部一致状态的视图 - Lit 不会重新渲染子组件,除非它们的属性发生变化(在这种情况下,他们自己处理)。然后,您可以让它们在它们之间切换时保持一致的高度。