我们有一个项目需要实施著名的Net Promoter Score或NPS反馈。很无聊,tbh。您需要拥有的那些相对微不足道的UI之一。 ("Does this spark joy?"绝对是一个清晰的“否。” )。
但是,有一个充分的理由收集这样的用户反馈,我们想拥有它。我立即认为这样的事情是单独的组成部分(主要是avoid doing it again)是有意义的,所以我决定这样做。
这是我构建可重复使用版本的过程。该博客再次适用于Vaadin,但是原理和“构建可重复使用的组件” - 在任何网络或IU框架上都有意义。
创建一个新的附加项目
可重用性的第一步:我们想创建一个单独的附加项目。我从GitHub使用了Vaadin默认addon-template,并在我的帐户下创建了一个新的存储库。该项目是一个很好的起点,因为它为包装和分发提供了样板。
克隆本地项目
接下来,在Visual Studio Code中本地克隆存储库项目。我正在使用Dev Containers与其他项目分开运行该项目。有一个现成的Java容器,我将Maven添加到该容器中。
vaadin提示:升级到v24
在撰写本文时,模板项目仍在较旧的vaadin 23上。因此,pom.xml需要进行较小的更新以使其与最新的vaadin版本兼容。
- vaadin版本为24.0.5
- Java版本为17
- 码头版本为11.0.15
UI代码
就像我一开始说的那样,UI非常简单,并且代码创建的代码不是太多:
public NPS() {
Span title = new Span("On a scale of 1 to 10, how likely would you recommend this to your friend or colleague?");
HorizontalLayout buttons = new HorizontalLayout();
buttons.add(new Text("Not likely"));
for (int i = 1; i <= 10; i++) {
Button button = new Button(String.valueOf(i), e -> {
int score = Integer.parseInt(e.getSource().getText());
Notification.show("Changed to "+score);
});
buttons.add(button);
}
buttons.add(new Text("Very likely"));
this.add(title, buttons);
}
因此,水平布局中的标题和按钮列表。如果您想尝试并使用"copy-paste reusability",这已经是可用的。
考虑组件可重复使用性
制作可重复使用的组件时,您想考虑一些事情。记录组件的最简单方法是创建一个自称的API。
- 组件UX。您需要键盘导航吗?鼠标悬停?捷径?我建议保持安全,将existing components结合在一起,并谨慎地使您的自定义解决方案。
- 组件配置或DX。您希望能够以各种方式改变文本和行为。 combinations can get tricky,所以您想经过各种测试。
- ui集成。您的组件是否仅使用(即单组分应用程序)?它会在弹出窗口中,还是它是其他UI的一部分? 数据集成。您的组件发射事件吗?它支持数据绑定吗?在服务器上缓存多少数据,浏览器可以处理多少?
- 兼容性。您正在使用什么框架版本?您希望用户使用哪个版本? Java版本怎么样?请记住,依赖项与Venn diagrams一样工作,因此请保持清单。
- 测试。如何自动化测试。如前所述,状态的配置可能会很棘手,因此您想在这里保持良好状态,以确保找到边缘案例。
- 文档。如果您在API方面做得好,则该部分应该很简单。专注于描述开发人员用例,然后跳过“此方法x”样式文档。
可能需要一两个回合才能使一切正确,但最好从您使用它的“真实应用程序”开始,并编写使用组件的代码。不是为了满足成熟的TDD,这是我为测试所做的:
final NPS nps = new NPS();
nps.setId("nps"); // This is for automated tests
// Button to start the feed process
add(new Button("Ask NPS", e -> {
add(nps);
}));
// Get the score and remove component
nps.addValueChangeListener(e-> {
Notification.show("Value changed from "+e.getOldValue()+" to "+e.getValue());
add(new Paragraph("NPS: " +e.getOldValue()+" -> "+e.getValue()));
remove(nps);
});
// Edit the the score
add(new Button("Edit score", e -> {
nps.setValue((int)Math.ceil(Math.random()*10));
add(nps);
}));
这是在AddonView.java
中实现的,也用于自动测试。这不是真实的事情,而是模拟我们在实际应用中的方案。
基本业务逻辑
由于NPS组件显然是具有单个可编辑值的“字段组件”,因此我们可以在此处重复使用框架功能。扩展CustomField为我们提供了价值输入和事件所需的大多数功能。我们只需要实施以下内容:
protected Integer generateModelValue() {
return this.score;
}
protected void setPresentationValue(Integer score) {
this.score = score;
}
我们的测试案例已经显示出仅阅读支持的问题。我们希望值可见,但输入已禁用。这些需要另外两种方法要实现。
首先,突出显示选择。我们使用“成功颜色”来做到这一点。
private void updateButtonSate() {
this.buttons
.getChildren()
.filter(c -> c instanceof Button)
.forEach(c -> {
Button b = (Button)c;
if (score != null && score.equals(Integer.parseInt(b.getText()))) {
b.addClassName(LumoUtility.Background.SUCCESS_50);
b.addClassName(LumoUtility.TextColor.SUCCESS_CONTRAST);
} else {
b.removeClassName(LumoUtility.Background.SUCCESS_50);
b.removeClassName(LumoUtility.TextColor.SUCCESS_CONTRAST);
};
});
}
然后,当我们处于仅阅读状态时,另一个可以禁用按钮。
public void setReadOnly(boolean readOnly) {
super.setReadOnly(readOnly);
this.buttons
.getChildren()
.filter(c -> c instanceof Button)
.forEach(c -> ((Button)c).setEnabled(!readOnly));
}
现在我们有事件,我们得到了组件价值簿记。
发布,发布
“ Release early, release often”,对吗?这就是创建一个简单的应用程序,该应用程序从用户那里收集NPS反馈。如您所见,它只是Web UI部分,您仍然需要存储数据并计算最终分数。
您可能拥有您的自定义数据库,我们仍然需要打包组件以进行分发,但是我将在下一篇博客文章中显示一些简单的选项。同时:在github.com/samie/nps上查看组件。
这种可重复使用实际上会引起欢乐,但是现在轮到您:以1到10的比例,您有可能向您的朋友或同事推荐此NPS调查?在下面发表评论。