跳转至

$dispatch

$dispatch 是一个用于派发浏览器事件的便捷快捷方式。

<div @notify="alert('Hello World!')">
    <button @click="$dispatch('notify')">
        Notify
    </button>
</div>

你也可以在派发事件时附带传递数据。这些数据可以通过事件的 .detail 属性访问:

<div @notify="alert($event.detail.message)">
    <button @click="$dispatch('notify', { message: 'Hello World!' })">
        Notify
    </button>
</div>

在底层,$dispatch 是对更冗长的 API 的封装:element.dispatchEvent(new CustomEvent(...))

关于事件传播的说明

请注意,由于事件冒泡机制,当你需要捕获从同一嵌套层级下的节点发出的事件时,需要使用 .window 修饰符:

示例:

<!-- 🚫 不生效 -->
<div x-data>
    <span @notify="..."></span>
    <button @click="$dispatch('notify')">Notify</button>
</div>

<!-- ✅ 可以工作(因为使用了 .window) -->
<div x-data>
    <span @notify.window="..."></span>
    <button @click="$dispatch('notify')">Notify</button>
</div>

第一个示例不生效的原因是,当 notify 被派发后,它会传播到共同的祖先元素 div,而不是其兄弟元素 <span>。第二个示例可以工作,因为兄弟元素在 window 层级监听 notify 事件,自定义事件最终会冒泡到 window。

派发到其他组件

你也可以利用前面的技术让组件之间相互通信:

示例:

<div
    x-data="{ title: 'Hello' }"
    @set-title.window="title = $event.detail"
>
    <h1 x-text="title"></h1>
</div>

<div x-data>
    <button @click="$dispatch('set-title', 'Hello World!')">Click me</button>
</div>
<!-- 点击后,h1 的内容将设置为 "Hello World!"。 -->

派发到 x-model

你也可以使用 $dispatch() 触发 x-model 数据绑定的数据更新。例如:

<div x-data="{ title: 'Hello' }">
    <span x-model="title">
        <button @click="$dispatch('input', 'Hello World!')">Click me</button>
        <!-- 按下按钮后,`x-model` 将捕获冒泡的 "input" 事件,并更新 title -->
    </span>
</div>

这为创建可通过 x-model 设置值的自定义输入组件打开了大门。

可取消的事件

你可以使用 $dispatch 的返回值来检查事件是否被取消。这在你想阻止某个操作的默认行为时很有用。

<div x-data x-on:open="$event.preventDefault()">
    <div x-data="{ open: false }">
        <button @click="if($dispatch('open')){ open = true; }">Click me</button>
        <!-- 按下按钮时,会派发一个事件,只有当结果为 truthy(没有被任何处理程序阻止)时,内容才会显示 -->

        <div x-show="open">
            <h1>Hello</h1>
        </div>
    </div>
</div>

当你希望通过事件处理程序来阻止打开/关闭模态框等操作时,这会很有用。

覆盖选项

你可以使用 $dispatch 的第三个参数来覆盖事件的默认选项。例如,你可以将 bubbles 设置为 false

<!-- 🚫 不生效,因为事件在父元素上监听 -->
<div x-data="{ title: 'Hello' }" x-on:update-title="title = $event.detail">
    <button @click="$dispatch('update-title', 'Hello World!', {bubbles: false})">Click me</button>
</div>

<!-- ✅ 可以工作,因为事件在同一个元素上监听 -->
<div x-data="{ title: 'Hello' }">
    <button x-on:update-title="title = $event.detail" @click="$dispatch('update-title', 'Hello World!', {bubbles: false})">Click me</button>
</div>

这在你想阻止事件冒泡到父元素时很有用。