查看源代码 Phoenix.LiveView.JS (Phoenix LiveView v0.20.17)
提供用于在客户端执行 JavaScript 实用程序操作的命令。
JS 命令支持各种实用程序操作,用于满足常见的客户端需求,例如添加或删除 CSS 类、设置或删除标签属性、显示或隐藏内容以及使用动画进行过渡。虽然这些操作可以通过客户端钩子来实现,但 JS 命令是 DOM 修补感知的,因此通过 JS API 应用的操作将保留在来自服务器的修补程序中的元素上。
除了纯粹的客户端实用程序之外,JS 命令还包括一个丰富的 push
API,用于扩展默认的 phx-
绑定推送,并提供选项以自定义目标、加载状态和额外的有效负载值。
客户端实用程序命令
包含以下实用程序
add_class
- 向元素添加类,可以选择过渡remove_class
- 从元素中删除类,可以选择过渡toggle_class
- 设置或删除元素的类,可以选择过渡set_attribute
- 在元素上设置属性remove_attribute
- 从元素中删除属性toggle_attribute
- 基于属性存在情况设置或删除元素属性。show
- 显示元素,可以选择过渡hide
- 隐藏元素,可以选择过渡toggle
- 根据可见性显示或隐藏元素,可以选择过渡transition
- 对元素应用临时过渡以进行动画dispatch
- 向元素分派 DOM 事件
例如,以下模态组件可以在客户端上显示或隐藏,而无需访问服务器
alias Phoenix.LiveView.JS
def hide_modal(js \\ %JS{}) do
js
|> JS.hide(transition: "fade-out", to: "#modal")
|> JS.hide(transition: "fade-out-scale", to: "#modal-content")
end
def modal(assigns) do
~H"""
<div id="modal" class="phx-modal" phx-remove={hide_modal()}>
<div
id="modal-content"
class="phx-modal-content"
phx-click-away={hide_modal()}
phx-window-keydown={hide_modal()}
phx-key="escape"
>
<button class="phx-modal-close" phx-click={hide_modal()}>✖</button>
<p><%= @text %></p>
</div>
</div>
"""
end
增强型推送事件
当 phx-
事件推送到服务器时,push/1
命令允许您扩展内置的推送事件处理。例如,您可能希望针对特定组件,指定要包含在事件中的额外有效负载值,将加载状态应用于外部元素等。例如,给定此基本 phx-click
事件
<button phx-click="inc">+</button>
假设您需要针对当前组件,并在客户端等待服务器确认时将加载状态应用于父容器
alias Phoenix.LiveView.JS
<button phx-click={JS.push("inc", loading: ".thermo", target: @myself)}>+</button>
推送命令还可以与所有其他实用程序组合使用。例如,要在推送时添加一个类
<button phx-click={
JS.push("inc", loading: ".thermo", target: @myself)
|> JS.add_class("warmer", to: ".thermo")
}>+</button>
任何 phx-value-*
属性也将包含在有效负载中,它们的值将被直接提供给 push/1
的值覆盖。任何 phx-target
属性也将被使用并被覆盖。
<button
phx-click={JS.push("inc", value: %{limit: 40})}
phx-value-room="bedroom"
phx-value-limit="this value will be 40"
phx-target={@myself}
>+</button>
使用 JS.dispatch/1
和 window.addEventListener
的自定义 JS 事件
dispatch/1
可用于向元素分派自定义 JavaScript 事件。例如,您可以使用 JS.dispatch("click", to: "#foo")
,向元素分派点击事件。
这也意味着您可以使用 JavaScript 的 window.addEventListener
将您的元素增强为自定义事件,并使用 dispatch/1
调用它们。例如,假设您希望在应用程序中提供复制到剪贴板的功能。您可以为它添加一个自定义事件
window.addEventListener("my_app:clipcopy", (event) => {
if ("clipboard" in navigator) {
const text = event.target.textContent;
navigator.clipboard.writeText(text);
} else {
alert("Sorry, your browser does not support clipboard copy.");
}
});
现在,您可以拥有这样的按钮
<button phx-click={JS.dispatch("my_app:clipcopy", to: "#element-with-text-to-copy")}>
Copy content
</button>
dispatch/1
与 window.addEventListener
的结合是增加您可以在 LiveView 代码中从客户端触发的操作数量的强大机制。
您还可以使用 window.addEventListener
监听从服务器推送的事件。您可以在我们的 JS 交互性指南 中了解更多信息。
总结
类型
函数
向元素添加类。
names
- 一个包含要添加的一个或多个类名的字符串。
选项
:to
- 一个可选的 DOM 选择器,用于向其添加类。默认为交互式元素。:transition
- 要在添加类之前应用的类字符串,或一个包含过渡类、要应用以启动过渡的类和结束过渡类的 3 元组,例如:{"ease-out duration-300", "opacity-0", "opacity-100"}
:time
- 应用:transition
过渡的时间(以毫秒为单位)。默认为 200。
示例
<div id="item">My Item</div>
<button phx-click={JS.add_class("highlight underline", to: "#item")}>
highlight!
</button>
参见 add_class/1
.
参见 add_class/1
.
向 DOM 分派事件。
event
- 要分派的字符串事件名称。
注意:所有分派的事件都属于 CustomEvent 类型,除了 "click"
。对于 "click"
,会分派一个 MouseEvent 以正确模拟 UI 点击。
对于发出的 CustomEvent
,事件详细信息将包含一个 dispatcher
,它引用将 JS 事件分派到目标元素的 DOM 节点。
选项
:to
- 一个可选的 DOM 选择器,用于向其分派事件。默认为交互式元素。:detail
- 一个可选的详细信息映射,与客户端事件一起分派。详细信息将在event.detail
属性中对事件监听器可用。:bubbles
– 一个布尔标志,指示是否冒泡事件。默认为true
。
示例
window.addEventListener("click", e => console.log("clicked!", e.detail))
<button phx-click={JS.dispatch("click", to: ".nav")}>Click me!</button>
参见 dispatch/2
.
执行位于元素属性中的 JS 命令。
attr
- 指定 JS 命令的字符串属性
选项
:to
- 一个可选的 DOM 选择器,用于从中获取属性。默认为当前元素。
示例
<div id="modal" phx-remove={JS.hide("#modal")}>...</div>
<button phx-click={JS.exec("phx-remove", to: "#modal")}>close</button>
参见 exec/1
.
参见 exec/1
.
将焦点发送到选择器。
选项
:to
- 一个可选的 DOM 选择器,用于向其发送焦点。默认为当前元素。
示例
JS.focus(to: "main")
参见 focus/1
.
将焦点发送到选择器中的第一个可聚焦子元素。
选项
:to
- 一个可选的 DOM 选择器,用于聚焦。默认为当前元素。
示例
JS.focus_first(to: "#modal")
参见 focus_first/1
.
隐藏元素。
选项
:to
- 一个可选的 DOM 选择器,用于隐藏。默认为交互式元素。:transition
- 要在隐藏之前应用的类字符串,或一个包含过渡类、要应用以启动过渡的类和结束过渡类的 3 元组,例如:{"ease-out duration-300", "opacity-100", "opacity-0"}
:time
- 应用:transition
过渡的时间(以毫秒为单位)。默认为 200。
在此过程中,以下事件将被分派到隐藏的元素
- 当操作在客户端上触发时,会分派
phx:hide-start
。 - 在
:time
指定的时间之后,会分派phx:hide-end
。
示例
<div id="item">My Item</div>
<button phx-click={JS.hide(to: "#item")}>
hide!
</button>
<button phx-click={JS.hide(to: "#item", transition: "fade-out-scale")}>
hide fancy!
</button>
参见 hide/1
.
向服务器发送补丁事件并更新浏览器的 pushState 历史记录。
选项
:replace
- 是否替换浏览器的 pushState 历史记录。默认值为false
。
示例
JS.patch("/my-path")
参见 patch/1
.
参见 patch/1
.
将焦点集中在最后推送的元素上。
示例
JS.pop_focus()
将事件推送到服务器。
event
- 要推送的字符串事件名称。
选项
:target
- 要推送到的选择器或组件 ID。此值将覆盖元素上存在的任何phx-target
属性。:loading
- 要将 phx 加载类应用到的选择器。:page_loading
- 布尔值,用于触发此推送的 phx:page-loading-start 和 phx:page-loading-stop 事件。默认值为false
。:value
- 要发送到服务器的值映射。这些值将与元素上存在的任何phx-value-*
属性合并。合并时所有键都将被视为字符串。
示例
<button phx-click={JS.push("clicked")}>click me!</button>
<button phx-click={JS.push("clicked", value: %{id: @id})}>click me!</button>
<button phx-click={JS.push("clicked", page_loading: true)}>click me!</button>
参见 push/1
.
参见 push/1
.
将焦点从源元素推送到稍后弹出。
选项
:to
- 要推送焦点的可选 DOM 选择器。默认值为当前元素。
示例
JS.push_focus()
JS.push_focus(to: "#my-button")
参见 push_focus/1
.
从元素中删除属性。
attr
- 要删除的字符串属性名称。
选项
:to
- 要从中删除属性的可选 DOM 选择器。默认值为交互元素。
示例
<button phx-click={JS.remove_attribute("aria-expanded", to: "#dropdown")}>
hide
</button>
从元素中删除类。
names
- 包含一个或多个要删除的类名的字符串。
选项
:to
- 要从中删除类的可选 DOM 选择器。默认值为交互元素。:transition
- 要在删除类之前应用的类字符串,或包含过渡类、要应用于启动过渡的类和结束过渡类的 3 元组,例如:{"ease-out duration-300", "opacity-0", "opacity-100"}
:time
- 应用:transition
过渡的时间(以毫秒为单位)。默认为 200。
示例
<div id="item">My Item</div>
<button phx-click={JS.remove_class("highlight underline", to: "#item")}>
remove highlight!
</button>
参见 remove_class/1
.
参见 remove_class/1
.
在元素上设置属性。
接受包含字符串属性名称/值对的元组。
选项
:to
- 要添加属性的可选 DOM 选择器。默认值为交互元素。
示例
<button phx-click={JS.set_attribute({"aria-expanded", "true"}, to: "#dropdown")}>
show
</button>
参见 set_attribute/1
.
参见 set_attribute/1
.
显示元素。
选项
:to
- 要显示的可选 DOM 选择器。默认值为交互元素。:transition
- 要在显示之前应用的类字符串,或包含过渡类、要应用于启动过渡的类和结束过渡类的 3 元组,例如:{"ease-out duration-300", "opacity-0", "opacity-100"}
:time
- 应用:transition
过渡的时间(以毫秒为单位)。默认为 200。:display
- 显示时要设置的可选显示值。默认值为"block"
。
在此过程中,以下事件将被分派到显示的元素
- 当在客户端触发操作时,将分派
phx:show-start
。 - 在
:time
指定的时间后,将分派phx:show-end
。
示例
<div id="item">My Item</div>
<button phx-click={JS.show(to: "#item")}>
show!
</button>
<button phx-click={JS.show(to: "#item", transition: "fade-in-scale")}>
show fancy!
</button>
参见 show/1
.
切换元素可见性。
选项
:to
- 要切换的可选 DOM 选择器。默认值为交互元素。:in
- 切换进来时要应用的类字符串,或包含过渡类、要应用于启动过渡的类和结束过渡类的 3 元组,例如:{"ease-out duration-300", "opacity-0", "opacity-100"}
:out
- 切换出去时要应用的类字符串,或包含过渡类、要应用于启动过渡的类和结束过渡类的 3 元组,例如:{"ease-out duration-300", "opacity-100", "opacity-0"}
:time
- 应用过渡:in
和:out
类的毫秒数。默认值为 200。:display
- 切换进来时要设置的可选显示值。默认值为"block"
。
当切换在客户端完成时,将向切换的元素分派 phx:show-start
或 phx:hide-start
,以及 phx:show-end
或 phx:hide-end
事件。
示例
<div id="item">My Item</div>
<button phx-click={JS.toggle(to: "#item")}>
toggle item!
</button>
<button phx-click={JS.toggle(to: "#item", in: "fade-in-scale", out: "fade-out-scale")}>
toggle fancy!
</button>
参见 toggle/1
.
基于属性存在情况设置或删除元素属性。
接受包含两个或三个元素的元组
{attr, val}
- 将属性设置为给定值或将其删除{attr, val1, val2}
- 在val1
和val2
之间切换属性
选项
:to
- 要设置或删除属性的可选 DOM 选择器。默认值为交互元素。
示例
<button phx-click={JS.toggle_attribute({"aria-expanded", "true", "false"}, to: "#dropdown")}>
toggle
</button>
<button phx-click={JS.toggle_attribute({"open", "true"}, to: "#dialog")}>
toggle
</button>
根据存在情况添加或删除元素类。
names
- 包含一个或多个要切换的类名的字符串。
选项
:to
- 要定位的可选 DOM 选择器。默认值为交互元素。:transition
- 要在添加类之前应用的类字符串,或一个包含过渡类、要应用以启动过渡的类和结束过渡类的 3 元组,例如:{"ease-out duration-300", "opacity-0", "opacity-100"}
:time
- 应用:transition
过渡的时间(以毫秒为单位)。默认为 200。
示例
<div id="item">My Item</div>
<button phx-click={JS.toggle_class("active", to: "#item")}>
toggle active!
</button>
元素过渡。
transition
- 要在删除类之前应用的类字符串,或包含过渡类、要应用于启动过渡的类和结束过渡类的 3 元组,例如:{"ease-out duration-300", "opacity-0", "opacity-100"}
过渡对于临时向元素添加动画类很有用,例如用于突出显示内容更改。
选项
:to
- 要应用过渡的可选 DOM 选择器。默认值为交互元素。:time
- 应用:transition
过渡的时间(以毫秒为单位)。默认为 200。
示例
<div id="item">My Item</div>
<button phx-click={JS.transition("shake", to: "#item")}>Shake!</button>
参见 transition/1
.
参见 transition/1
.