跳转至

$id

$id 是一个魔术属性,用于生成元素的 ID,并确保它不会与页面上其他相同名称的 ID 冲突。

这个工具在构建可复用组件(通常在后台模板中)时非常有用,这些组件可能在页面上出现多次,并且需要使用 ID 属性。

输入组件、模态框、列表框等都会从这个工具中受益。

基本用法

假设你的页面上有两个 input 元素,你希望它们拥有彼此不同的唯一 ID,可以这样做:

<input type="text" :id="$id('text-input')">
<!-- id="text-input-1" -->

<input type="text" :id="$id('text-input')">
<!-- id="text-input-2" -->

如你所见,$id 接收一个字符串,并生成一个在页面上唯一的带后缀的 ID。

使用 x-id 进行分组

现在假设你仍然有这两个 input 元素,但这次你需要为它们各自添加 <label> 元素。

这就出现了一个问题:你需要能够重复引用同一个 ID 两次——一次用于 <label>for 属性,另一次用于 input 的 id 属性。

以下是一种你可能想到的实现方式,是完全有效的:

<div x-data="{ id: $id('text-input') }">
    <label :for="id"> <!-- "text-input-1" -->
    <input type="text" :id="id"> <!-- "text-input-1" -->
</div>

<div x-data="{ id: $id('text-input') }">
    <label :for="id"> <!-- "text-input-2" -->
    <input type="text" :id="id"> <!-- "text-input-2" -->
</div>

这种方法没问题,但在组件作用域中命名和存储 ID 会显得繁琐。

为了以更灵活的方式完成同样的任务,你可以使用 Alpine 的 x-id 指令为一组 ID 声明一个"id 作用域":

<div x-id="['text-input']">
    <label :for="$id('text-input')"> <!-- "text-input-1" -->
    <input type="text" :id="$id('text-input')"> <!-- "text-input-1" -->
</div>

<div x-id="['text-input']">
    <label :for="$id('text-input')"> <!-- "text-input-2" -->
    <input type="text" :id="$id('text-input')"> <!-- "text-input-2" -->
</div>

如你所见,x-id 接受一个 ID 名称数组。在该作用域内的任何 $id() 使用都会共享同一个 ID。可以将它们理解为"id 组"。

嵌套

你可能已经猜到了,你可以自由地嵌套这些 x-id 组,像这样:

<div x-id="['text-input']">
    <label :for="$id('text-input')"> <!-- "text-input-1" -->
    <input type="text" :id="$id('text-input')"> <!-- "text-input-1" -->

    <div x-id="['text-input']">
        <label :for="$id('text-input')"> <!-- "text-input-2" -->
        <input type="text" :id="$id('text-input')"> <!-- "text-input-2" -->
    </div>
</div>

带键值的 ID(用于循环)

有时,在 ID 末尾添加额外的后缀以在循环中标识它会很有帮助。

为此,$id() 接受一个可选的第二个参数,该参数将作为后缀添加到生成的 ID 末尾。

一个常见的需求示例是列表框组件,它使用 aria-activedescendant 属性来告诉辅助技术列表中哪个元素是"活跃的":

<ul
    x-id="['list-item']"
    :aria-activedescendant="$id('list-item', activeItem.id)"
>
    <template x-for="item in items" :key="item.id">
        <li :id="$id('list-item', item.id)">...</li>
    </template>
</ul>

这是一个不完整的列表框示例,但应该足以演示这样一种场景:在一个组中,每个 ID 在页面上需保持唯一,同时在循环中需要带键值,以便可以引用该组中的单个 ID。