$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。