Partial state changes for Vaadin's AbstractJavascriptCom

Partial state changes for Vaadin's AbstractJavascriptComponent

本文关键字:AbstractJavascriptCom Vaadin state changes for Partial      更新时间:2023-09-26

我正在实现一个基于JavaScript的Vaadin组件,该组件需要显示和更新一个相对较大的数据集。我通过扩展AbstractJavaScriptComponent来实现这一点。

我试图让JS端尽可能地"愚蠢",使用RPC将用户交互委派给服务器,并更新共享状态。然后使用新状态调用JS连接器包装器的onStateChange函数,从而相应地更新DOM。

我有两个问题:

  1. 我不想每次更新一小部分时都传输整个数据集
  2. 我也不想每次都完全重建UI

我可以通过保持以前的状态并比较其中的一些部分来解决第二个问题,以找出发生了什么变化,并且只进行必要的DOM更改。但这仍然留下了第一个问题。

我是否必须停止使用Vaadin的共享状态机制,而只使用RPC来传达对状态的更改?

更新:我一直在做一些测试,Vaadin的共享状态机制在效率方面确实很糟糕:

每当组件调用getState()以更新状态对象中的某些属性(甚至不更新任何内容)时,整个状态对象都会被传输。据我所见,避免这种情况的唯一方法是不使用共享状态机制,而是使用RPC调用将特定的状态更改传达给客户端。

RPC方法中有一些问题需要解决,例如:如果在一个请求/响应周期内多次更改值,则不希望进行多次RPC调用。相反,您希望只发送最后一个值,就像共享状态机制只发送响应中的最终状态一样。您可以为要单独发送的状态的每个部分保留脏标志(或者只保留上一个状态的副本并进行比较),但您需要在请求处理结束时以某种方式触发RPC调用。如何做到这一点?

欢迎对此有任何想法!

更新2

Vaadin8修复了根本问题:它只发送更改后的状态属性。此外,当只进行RPC调用(并且不更改任何状态)时,它不再在JS连接器上调用onStateChange()

OP正确地指出,共享状态同步对于基于AbstractJavaScriptComponent的组件来说是低效的。当连接器被标记为脏时,整个状态对象被串行化,并可用于Javascript连接器的onStateChange方法。其他非javascript组件仅通过发送更改来更智能地处理状态更新。代码中发生这种情况的确切位置是com.vaadin.server.LegacyCommunicationManager.java 中的第97行

boolean supportsDiffState = !JavaScriptConnectorState.class
            .isAssignableFrom(stateType);

我不知道为什么对基于AbstractJavaScriptComponent的组件以不同的方式处理状态更新。也许这是为了简化javascript连接器,并消除从delta组装完整状态对象的需要。如果能在未来的版本中解决这个问题,那就太好了。

正如您所建议的,您可以完全省去JavaScriptComponentState,并依靠服务器->客户端RPC进行更新。在服务器端组件中保留脏标志,或者通过任何需要的机制比较旧状态和新状态。

要合并这些更改并为每个更改只发送一个RPC调用,可以在服务器端组件中重写beforeClientResponse(boolean initial)。这是在向客户端发送响应之前调用的,是您添加一组RPC调用以更新客户端组件的机会。

或者,您可以覆盖encodeState,在那里您可以自由支配向客户端发送您喜欢的任何JSON。您可以选择向super.encodeSate返回的基本JSON对象添加一个更改列表。您的javascript连接器可以在其onStateChange方法中进行适当的解释。

编辑后添加:在服务器端组件中调用getState()会将连接器标记为脏。如果您想在不将状态标记为脏的情况下获取状态,请改用getState(false)

在我们讨论了这一点之后,我为AbstractJavaScriptComponent创建了一个替代品,它传输状态增量,并包括一些额外的增强。它还处于早期阶段,但应该很有用。

https://github.com/emuanalytics/vaadin-enhancedjavascript

解决方案看似简单:基本上通过绕过com.vaadin.server.LegacyCommunicationManager.java:中的这行代码来重新启用状态差计算

boolean supportsDiffState = !JavaScriptConnectorState.class
        .isAssignableFrom(stateType);

Vaadin类不容易扩展,因此解决方案的实现很复杂,因此我不得不复制并重新实现6个类。

Vaadin的共享状态与您想要的开箱即用的状态完全一样:当一个组件第一次添加到DOM时,整个共享状态会从服务器转移到客户端,这样就可以显示该组件。之后,只传输更改。例如,通过调用component.setCaption("new caption")来更改可见组件的标题,Vaadin只将新的标题文本传输到客户端,并将其"合并"到组件的客户端共享状态实例。

相关文章:
  • 没有找到相关文章