从一开始,Vaadin就成为CUBA平台用户界面的基石和重要组成部分。 由于其创新的方法,它帮助CUBA将企业用户界面开发带到了一个非常有希望的(如今是默认)的WEB领域。 Vaadin最令人兴奋的部分之一是整个开发都是同构的,并且主要使用Java完成,从而避免了开发人员与相当不稳定且快速变化的前端世界进行交互。
如您所见,Vaadin的重要部分之一是功能丰富的UI(在Vaadin 8的情况下基于GWT小部件)。
与现代Web UI套件相比,即使在今天,Vaadin小部件仍然属于最复杂和最先进的部件,尤其是在企业需求方面。 首先,我们谈论的是在典型的CUBA应用程序组件中大量使用的组件,例如表,网格,组合框。 例如,只要尝试找到带有Table的流行UI工具包,即可提供拖放列重新排序或动态列控件。
Vaadin的故事
CUBA平台使用Vaadin的历史悠久。 该平台为用户提供了从Vaadin 5到Vaadin 8的几乎无缝迁移。为了提供这种迁移,我们必须在Vaadin之上构建并保持API。 此外,我们扩展了一些组件,甚至分叉框架本身为我们的客户提供独特的功能,并注入所需的扩展点。 在服务器端,平台提供数据绑定和数据感知组件,这是通用UI的最重要功能。
为了加快开发速度并启用快速开发工具(Studio),我们引入了XML描述符-建立数据绑定UI的声明性方法:
Pure Vaadin:
GridLayout tableHeader = new GridLayout( 3 , 2 ); Label nameLabel = new Label( "Field 1" ); nameLabel.setWidth(lastnameWidth + 2 * 6 , Unit.PIXELS); tableHeader.addComponent(nameLabel, 0 , 0 , 0 , 1 ); Label countryLabel = new Label( "Field 2" ); countryLabel.setWidth(countryWidth + 2 * 6 , Unit.PIXELS); tableHeader.addComponent( new Label( "Field 3" ), 1 , 0 ); Label bornLabel = new Label( "Field 4" ); bornLabel.setWidth(bornWidth + 2 * 6 , Unit.PIXELS); tableHeader.addComponent(bornLabel, 2 , 0 , 2 , 1 ); tableHeader.addComponent(countryFilterBox, 1 , 1 ); // Put the header and table inside a vertical layout layout.addComponent(tableHeader); layout.addComponent(table); // Adjust the table height a bit table.setPageLength(table.size());
我们设法建立了自己的组件列表(基于Vaadin原语):
- 组表
- 表格(以前是FieldGroup)
- PickerField
- LookupPickerField
- 令牌表
- MaskedField
- 建议字段
- 货币字段
话虽这么说,CUBA在Vaadin框架之上提供了很多功能,以使开发人员的生活更轻松,并使开发达到更高的水平。 CUBA团队进行了繁重的工作,以在更新基础的Vaadin框架时实现非常平滑,字面上看不见的迁移。
新挑战
定制和本地交互
GWT非常复杂,并且创建UI小部件是一个充满挑战且耗时的过程。 经验丰富的开发人员肯定知道在通过本机平台进行人工抽象时,您必须付出高昂的代价。 对于GWT,我们必须与Java世界中的浏览器JS API进行交互。
响应式布局
即使对于企业界面,针对不同屏幕尺寸的可调能力也已成为关键要求。 仅由于上述在本机平台上的额外抽象性,使响应式UI很难。 尽管您可以使用CssLayout或特殊的加载项来创建响应式UI,但是服务器端的标准布局和计算在这种情况下不能很好地发挥作用。
使用第三方库
Web的发展非常Swift,有大量的Web软件包(npm> 1M)在Vaadin 8应用程序中几乎没有用,因为它不使用现代的前端工具和构建系统。
GWT开发陷入困境
在某个时候,谷歌停止了GWT的积极开发。 这不仅与官方支持有关,而且与生态系统有关。
Vaadin流
为了对前端生态系统更加开放,Vaadin开始开发Vaadin框架的后继产品。 新方法的核心是Vaadin Flow ,该技术可为基于Web组件而不是GWT小部件的新UI层提供服务器端模型和基本数据绑定。
考虑下图:
如您所见,Vaadin已将基于GWT的客户端替换为基于本机Web技术的新客户端。
Vaadin成分
新的Vaadin 组件是Vaadin GWT小部件的后继产品。 它们是使用纯Web技术(HTML,Javascript)和Polymer 2库从头开始构建的Web组件。
Web组件
最初,Web组件是在大多数现代浏览器中实现的一组标准:
- 自定义元素
- 影子大教堂
- HTML模板
- HTML导入-> ES模块
长期以来,Web组件非常有前途,许多人(包括我在内)都将其视为React和Angular等框架的本地替代品,这些框架也利用基于组件的方法。 但是随着时间的流逝,这些标准中的一些已被浏览器丢弃,而另一些则需要进行重大改进,这一点变得显而易见。 如今,从上面的列表中,只有自定义元素和Shadow DOM仍用于Web应用程序开发中。 甚至从Chrome删除了HTML导入。 如今HTML模板看起来已经过时了,例如,新的Polymer方法: lit-html仅在幕后使用它们。
我们还尝试使用Web组件,这是我们尝试在Polymer库之上构建以客户端为中心的UI的一部分。 在某个时候,我们决定将工作转向基于React的方法,因为Polymer尽管具有Web Component支持解决方案的勇敢使命,但开发人员的经验很差,生态系统很小(即使已经存在了几年),最后还是不清楚not recommended
在新项目解决方案发布之时发布Polymer 3。 聚合物用户不得不等了将近一年,直到lit-html和LitElement最终发布。
从我们的经验中得出的另一个观察结果:尽管受到use the Platform
座右铭的拥护者的大力推动,但是在开发现代前端应用程序时,仍然几乎不可能摆脱转译/捆绑的步骤。 尽管标准正在为所有浏览器采用困难的方法和解决API带来困难,但社区创建了许多工具和库来解决相同的问题。
例如,Shadow DOM的主要目的是封装CSS样式,以免溢出到组件的本地DOM或从组件的本地DOM溢出。 这个想法很棒,但是大多数浏览器都花了几年的时间(幸好Edge迁移到了Chromium)。 同时,React生态系统由大量样式库实现,这些样式库可以解决相同的任务,甚至可以解决更多问题 ,而不会产生Shadow DOM的重大 陷阱 。
但是,Web组件具有非常重要的独特功能:它们是平台(浏览器)的一部分。 从理论上讲,它们不受任何特定框架的约束,是通用的,可以在任何地方使用。 从这个角度来看,这似乎是UI Kit或独立组件(而不是应用程序)的合理选择,不仅由Vaadin做出,而且例如由Ionic和SAP做出。
瓦丹14
基于Vaadin Flow的Vaadin 10已于2018年中期发布 。很快就很明显,UI套件缺少许多重要组件,只包含基本组件。 此外,客户端构建管道还包括一个Bower依赖管理器–该工具已于2017年弃用,并且不与事实上的标准npm生态系统相交。
因此,我们将Vaadin 10发布视为试验性的,并决定等到新技术变得更稳定为止。 在Vaadin 14 LTS 于 2019年8月到来之前,共有3个主要版本,其中包括对npm的高度支持和更强大的UI套件。 这敦促我们仔细观察并亲身体验Vaadin 14。
UI套件
即使没有深入研究代码库,很明显,与Vaadin 8小部件相比,许多属性和行为也发生了变化。 通常,这还不错,但是对于CUBA,这意味着在某些方面,不会直接替换当前支持的功能/ API。
在完整性方面,仍然有一些缺少的核心组件已在CUBA中使用:
- 日历
- 树
- 双柱
某些以前免费的组件和功能成为Pro组件的一部分:例如,RichTextArea现在是Pro组件的一部分,Vaadin Grid Pro中提供了Grid的编辑模式。
PickerField
作为评估过程的一部分,我们为Vaadin 14重新实现了CUBA的PickerField组件:
说到服务器端,Vaadin Flow提供了惊人的功能,可以使用Java API与客户端(DOM元素,事件等)进行交互。 Vaadin组件随附了便捷的Java API:
Accordion accordion = new Accordion(); ... accordion.open( 1 );
非Vaadin组件没有此类API,但是您仍然可以通过DOM API对任何元素使用通用方法:
例子1
if (value == null ) { getElement().removeProperty( "value" ); } else { getElement().setProperty( "value" , getStringRepresentation(value)); }
例子2
getElement().appendChild( new Element[]{Element.createText(text)});
尽管服务器端非常漂亮和清晰,但客户端却花了我们90%的精力。 我们首先要提到的是,核心Vaadin组件当前是由Polymer 2构建的。为了支持Vaadin 14+的Polymer 3,它们似乎已自动转换。 通常,Polymer 2和Polymer 3具有相同的API(这就是为什么可以进行自动转换的原因),但是,导入和样式声明之间存在细微的差异。
另一个棘手的话题是样式和自定义:由于Shadow DOM,您根本无法将样式应用于随机元素(仅适用于设计为可通过使用自定义CSS属性进行样式设置的元素)。 Vaadin组件具有用于自定义的插槽(Shadow DOM的另一个强大但复杂的部分)。 它们非常适合简单的用例,但是在尝试实现更高级的用例时,您很快就会遇到限制。
因此,在实现PickerField时,我们将通过复制粘贴样式和Vaadin组件的其他部分结束,并在本机input
元素之上构建该组件(从@vaadin导入的唯一可重用的东西是几个Mixins)。
我们不怪Vaadin,因为Vaadin尚未设计(也不应该)作为另一个UI套件的基础,它只是表明对我们来说,支持所有附加功能在客户端将是大量工作我们为开发人员提供了很长一段时间。 当前应该以Polymer 3为基础的作品(已经处于维护模式),所有已知的开发人员都遇到Polymer2的缺陷。
最新消息
就在撰写本文时,Vaadin宣布所有核心组件都将在TypeScript和LitElement上进行重写。 我们对这一决定持积极态度,因为我们在TypeScript方面的丰富经验证实,它可以避免JS中缺少静态类型所引起的大量错误,有助于理解代码库的结构,执行安全的重构等。
不过,LitElement / lit-html看起来有点令人怀疑:我们理解这一选择,因为它是Polymer的后继者,并利用了React发明的强大的声明式渲染(view = f(state))方法。 但是它仍然是:
- 很新 。
- 具有运行时(与Stencil和Svetle之类的已编译方法不同)。 为了同时支持基于聚合物和基于Lit的组件,Vaadin应将两个库都交付给客户端。
- IDE支持差。 有一些VS Code插件,但是IntelliJ / WebStorm中不提供支持 ,这使得点亮的模板看起来非常混乱。
- 不是SSR –友好。
出现了许多新问题:
LitElement + TypeScript是否将取代当前基于Polymer 3的方法来开发应用程序前端?
如果是,那么类似React的渲染将如何与服务器端Java API一起工作?
更新资料
Vaadin 15附带了客户端引导程序和TypeScript 支持 。
结论
Vaadin是一种独特的产品,可为Java提供便利的Web开发。 Vaadin Flow带来了全新的客户端方法,我们认为这是很有前途的。 但是,组件集仍在不断发展,并正在走向稳定。
我们可以肯定地说一件事:由于全新的客户端,我们将无法为从Vaadin Flow之上构建的新UI提供平滑的迁移路径。
同样,我们认为在客户端技术上开始在其之上进行所有CUBA组件的大规模迁移仍然有些模糊和不稳定。 我们决定将积极的开发推迟到新的Web组件集可用之前。 我们仍会密切关注Vaadin的发展,并准备在其变得更加稳定后对其进行重新评估。
同时,我们还试图提供一种替代的,友好的,客户端友好的方法来创建UI:请参阅我们最近关于TypeScript SDK和React Client的博客文章。
翻译自: https://www.javacodegeeks.com/2020/01/vaadin-10-as-the-future-of-cuba-ui.html