查看源代码 实时导航
LiveView 提供功能,允许使用 浏览器的 pushState API 进行页面导航。使用实时导航,页面会在不完全重新加载的情况下更新。
您可以通过两种方式触发实时导航
从客户端 — 通过将
patch={url}
或navigate={url}
传递给Phoenix.Component.link/1
组件来完成。从服务器 — 通过
Phoenix.LiveView.push_patch/2
或Phoenix.LiveView.push_navigate/2
来完成。
例如,在模板中,您不必编写以下内容
<.link href={~p"/pages/#{@page + 1}"}>Next</.link>
您可以编写
<.link patch={~p"/pages/#{@page + 1}"}>Next</.link>
或在 LiveView 中
{:noreply, push_patch(socket, to: ~p"/pages/#{@page + 1}")}
当您想要导航到当前 LiveView 时,必须使用“patch”操作,只需更新 URL 和当前参数,而无需挂载新的 LiveView。使用 patch 时,会调用 handle_params/3
回调,并将最小的更改集发送到客户端。有关更多信息,请参见下一节。
当您想要卸载当前 LiveView 并挂载新的 LiveView 时,必须使用“navigate”操作。您只能在同一个会话中“导航”不同的 LiveView。在重定向时,会在 LiveView 中添加 phx-loading
类,可以用来指示用户正在加载新页面。
如果您尝试修补到另一个 LiveView 或跨实时会话导航,将会触发完全的页面重新加载。这意味着您的应用程序将继续工作,以防您的应用程序结构发生变化,而这些变化没有反映在导航中。
下面是快速分解
<.link href={...}>
和redirect/2
是基于 HTTP 的,可以在任何地方工作,并且会执行完整的页面重新加载<.link navigate={...}>
和push_navigate/2
在同一个会话中跨 LiveView 工作。它们会挂载新的 LiveView,同时保留当前布局<.link patch={...}>
和push_patch/2
会更新当前 LiveView,并仅发送最小的差异,同时也会保留滚动位置
handle_params/3
在 mount/3
之后,在初始渲染之前,会调用 handle_params/3
回调。每当使用 <.link patch={...}>
或 push_patch/2
时,也会调用它。它将请求参数作为第一个参数接收,将 url 作为第二个参数接收,并将套接字作为第三个参数接收。
例如,假设您有一个 UserTable
LiveView 用于显示系统中的所有用户,您在路由器中将其定义为
live "/users", UserTable
现在要添加实时排序,您可以执行以下操作
<.link patch={path(~p"/users", sort_by: "name")}>Sort by name</.link>
单击后,由于我们正在导航到当前 LiveView,因此会调用 handle_params/3
。请记住,您永远不应该信任接收到的参数,因此您必须使用回调来验证用户输入并相应地更改状态
def handle_params(params, _uri, socket) do
socket =
case params["sort_by"] do
sort_by when sort_by in ~w(name company) -> assign(socket, sort_by: sort_by)
_ -> socket
end
{:noreply, load_users(socket)}
end
请注意,我们返回了 {:noreply, socket}
,其中 :noreply
表示不会向客户端发送任何额外信息。与其他 handle_*
回调一样,对 handle_params/3
内部的状态进行的更改会触发新的服务器渲染。
请注意,传递给 handle_params/3
的参数与传递给 mount/3
的参数相同。那么您如何决定使用哪个回调来加载数据呢?一般来说,数据应该始终在 mount/3
上加载,因为 mount/3
在每个 LiveView 生命周期中只调用一次。只有您希望通过 <.link patch={...}>
或 push_patch/2
更改的参数必须在 handle_params/3
上加载。
例如,假设您有一个博客。单个帖子的 URL 为:"/blog/posts/:post_id"。在帖子页面中,您有评论,并且它们是分页的。您使用 <.link patch={...}>
在用户每次分页时更新显示的评论,将 URL 更新为 "/blog/posts/:post_id?page=X"。在此示例中,您将在 mount/3
上访问 "post_id"
,并在 handle_params/3
上访问评论页面。
替换页面地址
LiveView 还允许替换当前浏览器 URL。当您希望某些事件更改 URL 但又不想污染浏览器的历史记录时,这很有用。这可以通过将 <.link replace>
选项传递给任何导航帮助器来完成。
同一页面中的多个 LiveView
LiveView 允许您在同一页面中拥有多个 LiveView,方法是在模板中调用 Phoenix.Component.live_render/3
。但是,只有在路由器中直接定义的 LiveView 才能使用此处描述的“实时导航”功能。这一点很重要,因为 LiveView 与您的路由器紧密配合,保证您只能导航到已知的路由。