Home

Documentation versions (currently viewingVaadin 24)
Documentation translations (currently viewingChinese)

本页面为机器翻译自官方文档,其原文位于 http://vaadin.com/docs。此翻译可能包含错误、不准确或不严谨之处。Vaadin 不保证或声明翻译内容的准确性、可靠性或时效性。

导航到视图

在本指南中,您将学习如何使用[classname]`RouterLink`和[methodname]`UI.navigate()`在视图之间进行导航。您还将了解如何通过将部分导航逻辑封装到您自己的API中来提升代码的可读性。最后,会有一个小型教程帮助您在实际Vaadin应用中应用这些概念。

路由链接

RouterLink`是创建用于导航的可点击链接的组件。在HTML中,它对应于锚点(<a>`)元素。

Tip
链接优于编程式导航,因为它们*提升了可访问性*。它们还允许用户在新的浏览器标签页中打开链接。

以下示例创建了一个指向[classname]`MainView`的链接:

Source code
Java
var link = new RouterLink("Home", MainView.class);
myLayout.add(link);

如果视图接受单个路由参数,您可以将参数值传递给[classname]`RouterLink`构造函数。

在以下示例中,[classname]`CustomerDetailsView`实现了[interfacename]`HasUrlParameter<T>`接口并接受一个字符串参数——客户的ID。该链接导航到ID为"cu1234"的客户详情页:

Source code
Java
var link = new RouterLink("Customer Details", CustomerDetailsView.class, "cu1234");
myLayout.add(link);

如果视图接受多个路由参数,您需要构造一个[classname]`RouteParameters`实例并将其传递给[classname]`RouterLink`构造函数。您可以以不同的方式构造它;详情请参阅其 API 文档

以下示例创建了一个带有两个路由参数的客户详情页链接;`customerId`的值为"cu1234",`mode`的值为"edit":

Source code
Java
var link = new RouterLink("Edit Customer", CustomerDetailsView.class,
    new RouteParameters(Map.of("customerId", "cu1234", "mode", "edit")));
myLayout.add(link);

有关路由参数的更多信息,请参阅 路由参数 指南。

编程式导航

使用链接不是在视图间导航的唯一方式。您可以在Java中通过调用任意[methodname]`UI.navigate()`方法来触发导航。通常您会在用户操作后(如按钮点击监听器内)这么做,但这不是必需条件。您也可以通过服务端推送等方式从后台线程触发导航。

[methodname]`UI.navigate()`的API与[classname]`RouterLink`类似。在下例中,用户点击按钮时,路由器会试图导航到主页:

Source code
Java
var button = new Button("Home");
button.addClickListener(event ->
    UI.getCurrent().navigate(MainView.class)
);

如果视图接受单个路由参数,您可以如下将参数值传递给[methodname]UI.navigate()

Source code
Java
var button = new Button("Customer Details");
button.addClickListener(event ->
    UI.getCurrent().navigate(CustomerDetailsView.class, "cu1234")
);

如果视图接受多个路由参数,您需要构造一个[classname]RouteParameters`实例并将其传递给[methodname]`UI.navigate(),方式如下:

Source code
Java
var button = new Button("Edit Customer");
button.addClickListener(event ->
    UI.getCurrent().navigate(CustomerDetailsView.class,
        new RouteParameters(Map.of("customerId", "cu1234", "mode", "edit"))
    )
);

自定义API

与其在代码库中到处调用[methodname]UI.navigate(),不如将导航逻辑封装进专用方法内。这种做法提高了代码的可读性、可维护性,并便于重构。

在以下示例中,[classname]`CustomerDetailsView`提供了一个静态方法,以给定ID导航到客户详情页面:

Source code
Java
@Route("customer")
public class CustomerDetailsView extends Main implements HasUrlParameter<String> {

    public static void showCustomerDetails(String customerId) {
        UI.getCurrent().navigate(CustomerDetailsView.class, customerId);
    }
    ...
}

当您需要导航到该视图时,只需这样调用方法:

Source code
Java
var button = new Button("Customer Details");
button.addClickListener(event ->
    CustomerDetailsView.showCustomerDetails("cu1234")
);

如果您需要传递多个路由参数或自定义参数类型,这种方式将更加有用。

在下例中,CustomerDetailsView`接受两个路由参数;值对象[classname]`CustomerId`与枚举[classname]`Mode

Source code
Java
@Route("customer/:customerId/:mode?(edit|view)") 1
public class CustomerDetailsView extends Main implements HasUrlParameter<String> {

    public enum Mode {
        edit, view
    }

    private static RouteParameters createRouteParameters(
            CustomerId customerId, Mode mode) {
        return new RouteParameters(
            Map.of(
                "customerId", customerId.toString(),
                "mode", mode.toString()
            )
        );
    }

    public static RouterLink createEditLinkTo(String text, CustomerId customerId) {
        return new RouterLink(text, CustomerDetailsView.class,
            createRouteParameters(customerId, Mode.edit));
    }

    public static void editCustomerDetails(CustomerId customerId) {
        UI.getCurrent().navigate(CustomerDetailsView.class,
            createRouteParameters(customerId, Mode.edit));
    }
    ...
}
  1. 这是一个带有两个路由参数的路由模板。

通过这种API,您可以像这样创建一个新的路由链接:

Source code
Java
CustomerId customerId = ...;
myLayout.add(CustomerDetailsView.createEditLinkTo("Edit Customer", customerId));

如果想以编程方式导航到视图,可如下操作:

Source code
Java
CustomerId customerId = ...;
var button = new Button("Edit Customer");
button.addClickListener(event ->
    CustomerDetailsView.editCustomerDetails(customerId)
);

React视图

到目前为止,所有示例均为Flow视图之间的导航。然而,您也可以从Flow视图导航到React视图。与Flow视图不同,React视图没有相应的Java类,导航时需要基于字符串的路由。

您可以使用锚元素进行导航,也可通过[methodname]`UI.navigate()`进行编程式导航。

在Flow中,您可以这样创建锚点:

Source code
Java
var link = new Anchor("path/to/react/view", "Link to React View");
myLayout.add(link);
Note
Vaadin将应用的http://developer.mozilla.org/en-US/docs/Web/HTML/Element/base[base URL]设置为主视图的路径,所有相对链接均基于此URL解析。这意味着在创建`Anchor`对象时无需考虑上下文路径。

您还可以以编程方式导航到React视图,方式如下:

Source code
Java
var button = new Button("Go to React view");
button.addClickListener(event -> UI.getCurrent().navigate("path/to/react/view"));

试一试

在本小教程中,您将学习如何通过*链接*和*编程式导航*在Flow视图之间切换。本例未涉及路由参数,相关内容请参阅其它专门指南。

搭建项目

首先,生成一个 带Flow UI的样板项目在IDE中打开,并以启用hotswap的方式 运行

Note
如果您已完成了 添加视图 的小教程,可以继续在同一项目中操作。
创建Links视图

现在,您将创建一个新视图,提供多种跳转到任务列表视图的方式。新建[packagename]`[application package].tutorial.ui.view`包,并在其中新建`LinksView`类:

Source code
LinksView.java
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.router.Route;

@Route("links")
public class LinksView extends Main {
    public LinksView() {
    }
}
添加路由链接

RouterLink`用于创建跳转到其它视图的可点击链接。修改[classname]`LinksView,以包含指向[classname]`TaskListView`的链接:

Source code
LinksView.java
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouterLink;

@Route("links")
public class LinksView extends Main {

    public LinksView() {
        add(new RouterLink("Task List", TaskListView.class));
    }
}

现在,在浏览器中访问:http://localhost:8080/links

鼠标悬停在“Task List”链接上,可看到其目标为 http://localhost:8080。点击该链接以跳转到任务列表视图后,再用*浏览器的后退按钮*返回。

编程式导航

接下来,您将添加一个按钮,点击后跳转到任务列表视图。修改[classname]LinksView,以包含[classname]Button

Source code
LinksView.java
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouterLink;

@Route("links")
public class LinksView extends Main {

    public LinksView() {
        add(new RouterLink("Task List", TaskListView.class));
        add(new Button("Task List",
                event -> UI.getCurrent().navigate(TaskListView.class)));
    }
}

切回浏览器。得益于*hotswap*,新的[guibutton]*Task List*按钮应已自动出现。点击按钮即可跳转至任务列表视图。

创建API

为了让导航方式更具复用性和可读性,您现在将为跳转到任务列表视图创建专用方法。

打开[classname]TaskListView,添加以下方法:

Source code
TaskListView.java
@Route("")
@PageTitle("Task List")
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Task List")
public class TaskListView extends Main {
    ...
    public static void showTasks() {
        UI.getCurrent().navigate(TaskListView.class);
    }
}

现在,更新[classname]LinksView,使其调用此方法,而不是直接调用[methodname]UI.getCurrent().navigate()

Source code
LinksView.java
@Route("links")
public class LinksView extends Main {

    public LinksView() {
        add(new RouterLink("Task List", TaskListView.class));
        add(new Button("Task List", event -> TaskListView.showTasks()));
    }
}

返回浏览器并点击按钮。它的效果与之前相同,但您的代码*更干净、更易维护*。

总结

您已经探索了多种在Flow视图之间导航的方式。以下是您所学内容:

  • 使用[classname]`RouterLink`创建导航链接。

  • 使用[methodname]`UI.navigate()`编程式导航。

  • 创建可复用的导航API,提升代码可读性。

既然已学会如何视图间切换,建议继续了解 导航传递数据 指南,以学习如何在导航过程中向视图传递数据。