出口
出口允许你通过使用 CSS 选择器从另一个 Stimulus 控制器中引用 Stimulus 控制器实例及其 控制器元素。
使用出口有助于跨控制器通信和协调,作为在控制器元素上分发自定义事件的替代方案。
它们在概念上类似于 Stimulus 目标,但不同之处在于它们引用 Stimulus 控制器实例及其关联的控制器元素。
<div>
<div class="online-user" data-controller="user-status">...</div>
<div class="online-user" data-controller="user-status">...</div>
...
</div>
...
<div data-controller="chat" data-chat-user-status-outlet=".online-user">
...
</div>
虽然目标是其自身控制器元素范围内的特定标记元素,但出口可以位于页面的任何位置,并且不一定必须在控制器范围内。
﹟ 属性和名称
data-chat-user-status-outlet
属性称为出口属性,其值为 CSS 选择器,你可以使用它来引用其他控制器元素,这些元素应该作为出口在主机控制器上可用。主机控制器中的出口标识符必须与目标控制器的标识符相同。
data-[identifier]-[outlet]-outlet="[selector]"
<div data-controller="chat" data-chat-user-status-outlet=".online-user"></div>
﹟ 定义
使用 static outlets
数组在你的控制器类中定义控制器标识符。此数组声明哪些其他控制器标识符可以用作此控制器上的出口
// chat_controller.js
export default class extends Controller {
static outlets = [ "user-status" ]
connect () {
this.userStatusOutlets.forEach(status => ...)
}
}
﹟ 属性
对于 static outlets
数组中定义的每个出口,Stimulus 会向你的控制器添加五个属性,其中 [name]
对应于出口的控制器标识符
类型 | 属性名称 | 返回类型 | 效果 |
---|---|---|---|
存在性 | has[Name]Outlet |
布尔值 |
测试 [name] 出口是否存在 |
单数 | [name]Outlet |
控制器 |
返回第一个 [name] 出口的 Controller 实例,如果不存在则抛出异常 |
复数 | [name]Outlets |
Array<Controller> |
返回所有 [name] 出口的 Controller 实例 |
单数 | [name]OutletElement |
元素 |
返回第一个 [name] 出口的 Controller Element ,如果不存在则抛出异常 |
复数 | [name]OutletElements |
Array<Element> |
返回所有 [name] 出口的 Controller Element |
注意:对于嵌套的 Stimulus 控制器属性,请务必省略命名空间分隔符,以便正确访问引用的出口
// chat_controller.js
export default class extends Controller {
static outlets = [ "admin--user-status" ]
selectAll(event) {
// returns undefined
this.admin__UserStatusOutlets
// returns controller reference
this.adminUserStatusOutlets
}
}
﹟ 访问控制器和元素
由于从 [name]Outlet
和 [name]Outlets
属性中获取 Controller
实例,因此还可以访问控制器实例定义的值、类、目标以及所有其他属性和函数
this.userStatusOutlet.idValue
this.userStatusOutlet.imageTarget
this.userStatusOutlet.activeClasses
还可以调用出口控制器可能定义的任何函数
// user_status_controller.js
export default class extends Controller {
markAsSelected(event) {
// ...
}
}
// chat_controller.js
export default class extends Controller {
static outlets = [ "user-status" ]
selectAll(event) {
this.userStatusOutlets.forEach(status => status.markAsSelected(event))
}
}
类似地,使用 Outlet Element 时,它允许在 Element
上调用任何函数或属性
this.userStatusOutletElement.dataset.value
this.userStatusOutletElement.getAttribute("id")
this.userStatusOutletElements.map(status => status.hasAttribute("selected"))
﹟ 出口回调
出口回调是 Stimulus 调用的特殊命名函数,可让你响应页面中添加或移除出口时的操作。
要观察出口更改,请定义名为 [name]OutletConnected()
或 [name]OutletDisconnected()
的函数。
// chat_controller.js
export default class extends Controller {
static outlets = [ "user-status" ]
userStatusOutletConnected(outlet, element) {
// ...
}
userStatusOutletDisconnected(outlet, element) {
// ...
}
}
﹟ 假设存在出口
在控制器中访问 Outlet 属性时,断言至少存在一个对应的 Outlet。如果声明缺失且未找到匹配的出口,Stimulus 将抛出异常
Missing outlet element "user-status" for "chat" controller
﹟ 可选出口
如果 Outlet 是可选的,或者要断言至少存在一个 Outlet,则必须首先使用存在属性检查 Outlet 的存在
if (this.hasUserStatusOutlet) {
this.userStatusOutlet.safelyCallSomethingOnTheOutlet()
}
﹟ 引用非控制器元素
如果你尝试将没有相应 data-controller
和标识符的元素声明为出口,Stimulus 将抛出异常
<div data-controller="chat" data-chat-user-status-outlet="#user-column"></div>
<div id="user-column"></div>
将导致
Missing "data-controller=user-status" attribute on outlet element for
"chat" controller`