Vaadin Flow:返回视图,视图不应从后端重新加载数据
Vaadin Flow: Returning to a view, the view should not reload data from the backend
从拆分出来。
给定一个带有 MainView extends AppLayout
、GridView
和 EmptyView
的 Vaadin Flow 19 应用,并且 @PreserveOnRefresh
注释用于 MainView
.
当return转到GridView
时,GridView
应该和之前的状态完全一样:
- 第一次使用
MainView
中的按钮打开 GridView
-> Grid 使用 DataProvider
从后端获取数据
- 在
TextField
中输入“蜘蛛侠”,标题为“stateCheck”
- 使用
MainView
中的按钮切换到 EmptyView
- 在真实应用中:在
EmptyView
和可能的其他视图中做一些事情
- return 到
GridView
第二次使用 MainView
中的按钮
然后 (1) 标题为“stateCheck”的 TextField
应显示值“Spiderman”
并且 (2) 网格仍应显示与之前相同的数据;它应该不从后端重新加载数据
观察到的行为:
(1) 可以,但 (2) 不行:网格总是调用 fetch
方法从后端获取数据。
如何实现所需的行为?
这是我的 GridView
的代码,它也伪造了后端 DataProvider
:
@Route(value = "grid", layout = MainView.class)
public class GridView extends VerticalLayout {
public GridView() {
final Grid<Person> g = new Grid(Person.class);
g.setColumns("name");
g.setDataProvider(DataProvider.fromCallbacks(q -> fetch(q), q -> count(q)));
add(g);
add(new TextField("State check"));
}
// fake DataProvider
private int count(Query<Person, Void> q) { return 3; }
private Stream<Person> fetch(Query<Person, Void> q) {
q.getLimit(); //vaadin checks these have been called
q.getOffset(); //vaadin checks these have been called
System.out.println("fetching again");
return Arrays.asList(new Person("1"), new Person("2"), new Person("3")).stream();
}
}
MainView
用于在GridView
和EmptyView
之间切换
@PreserveOnRefresh
public class MainView extends AppLayout {
private Component emptyBView;
private Component gridBView;
public MainView() {
final Button emptyB = new Button("Btn empty");
emptyB.addClickListener(e -> {
if (emptyBView == null) { emptyBView = new EmptyView();}
setContent(emptyBView);
});
addToNavbar(emptyB);
final Button gridB = new Button("Btn grid");
gridB.addClickListener(e -> {
if (gridBView == null) gridBView = new GridView();
setContent(gridBView);
});
addToNavbar(gridB);
}
}
这其实是有意为之的行为。当组件分离并在附加时重新连接时,需要删除服务器端数据提供者侦听器。原因是否则会有监听器积累并产生内存泄漏。如果您认为您的用户会经常使用刷新页面,您应该考虑向您的应用程序添加缓存以优化性能。
现在,人们可以考虑在 Grid 中以及在 Vaadin 框架中通过 API 对以前加载的数据行为进行这种缓存的想法,因为它可能是可取的,也可能不是可取的。它是特定于应用程序的。
如果刷新的用例确实是为了获取活动数据库的新鲜数据,那么实际上希望在刷新页面时加载数据。
如果希望避免对数据库的额外轰炸,因为已知数据是静态的,则需要缓存。
从
给定一个带有 MainView extends AppLayout
、GridView
和 EmptyView
的 Vaadin Flow 19 应用,并且 @PreserveOnRefresh
注释用于 MainView
.
当return转到GridView
时,GridView
应该和之前的状态完全一样:
- 第一次使用
MainView
中的按钮打开GridView
-> Grid 使用DataProvider
从后端获取数据 - 在
TextField
中输入“蜘蛛侠”,标题为“stateCheck” - 使用
MainView
中的按钮切换到 - 在真实应用中:在
EmptyView
和可能的其他视图中做一些事情 - return 到
GridView
第二次使用MainView
中的按钮
EmptyView
然后 (1) 标题为“stateCheck”的 TextField
应显示值“Spiderman”
并且 (2) 网格仍应显示与之前相同的数据;它应该不从后端重新加载数据
观察到的行为:
(1) 可以,但 (2) 不行:网格总是调用 fetch
方法从后端获取数据。
如何实现所需的行为?
这是我的 GridView
的代码,它也伪造了后端 DataProvider
:
@Route(value = "grid", layout = MainView.class)
public class GridView extends VerticalLayout {
public GridView() {
final Grid<Person> g = new Grid(Person.class);
g.setColumns("name");
g.setDataProvider(DataProvider.fromCallbacks(q -> fetch(q), q -> count(q)));
add(g);
add(new TextField("State check"));
}
// fake DataProvider
private int count(Query<Person, Void> q) { return 3; }
private Stream<Person> fetch(Query<Person, Void> q) {
q.getLimit(); //vaadin checks these have been called
q.getOffset(); //vaadin checks these have been called
System.out.println("fetching again");
return Arrays.asList(new Person("1"), new Person("2"), new Person("3")).stream();
}
}
MainView
用于在GridView
和EmptyView
@PreserveOnRefresh
public class MainView extends AppLayout {
private Component emptyBView;
private Component gridBView;
public MainView() {
final Button emptyB = new Button("Btn empty");
emptyB.addClickListener(e -> {
if (emptyBView == null) { emptyBView = new EmptyView();}
setContent(emptyBView);
});
addToNavbar(emptyB);
final Button gridB = new Button("Btn grid");
gridB.addClickListener(e -> {
if (gridBView == null) gridBView = new GridView();
setContent(gridBView);
});
addToNavbar(gridB);
}
}
这其实是有意为之的行为。当组件分离并在附加时重新连接时,需要删除服务器端数据提供者侦听器。原因是否则会有监听器积累并产生内存泄漏。如果您认为您的用户会经常使用刷新页面,您应该考虑向您的应用程序添加缓存以优化性能。
现在,人们可以考虑在 Grid 中以及在 Vaadin 框架中通过 API 对以前加载的数据行为进行这种缓存的想法,因为它可能是可取的,也可能不是可取的。它是特定于应用程序的。
如果刷新的用例确实是为了获取活动数据库的新鲜数据,那么实际上希望在刷新页面时加载数据。
如果希望避免对数据库的额外轰炸,因为已知数据是静态的,则需要缓存。