假设我有一个刀片组件,例如:
<input type="text" id="foo" name="{{$name}}"/>
<script>
$('#foo').whatever
</script>
IRL,此组件要复杂得多。您可以想象一个长格式,其中包含许多字段,这些字段具有通用名称,例如name
,description
,owner
...
然后我多次使用此组件,我再次提出foreach
,但我们可以想象到其他无法使用迭代器为组件提供ID的情况:
@foreach($items as $item)
@component('foo')
@endcomponent
@endforeach
如何确保id
的唯一性?
一种可能不好的解决方案是使用局部变量:
@php($id = uniqid())
<input type="text" id="{{$id}}" name="{{$name}}"/>
<script>
$('#{{$id}}').change(whatever)
</script>
有更好的方法吗?
答案 0 :(得分:3)
我会将项目传递给组件:
@component('foo', ['item' => $item])
您可以在其中执行以下操作:
<input type="text" id="foo_{{ $item->id }}"/>
答案 1 :(得分:1)
有同样的需求,找到了这个答案,正如OP所说,我更倾向于认为,由于组件需要它,所以它应该处理它。
我想出了这种选择。
// resources/views/components/button.blade.php
@php
$yourLibNameId = uniqid();
@endphp
<button data-your-lib-name-id="{{ $yourLibNameId }}">{{ $slot }}</button>
@push("script")
<script type="text/javascript" defer="true">
document.addEventListener("DOMContentLoaded", function() {
const button = document.querySelector("[data-your-lib-name-id='{{ $yourLibNameId }}']");
if (button instanceof HTMLElement) {
button.addEventListener("click", function() {
console.log("clicked");
});
// or do whatever needed to initialize the button...
}
});
</script>
@endpush
总结:
id
属性,而是使用data-x
属性不干扰id,并为使用此数据提供了适当的范围@push("script")
指令我将要为Material Components Web创建一个组件库,所以这就是我将要使用的内容(因此your-lib-name
)。
希望它可以帮助人们将其组件保持尽可能孤立的状态。
答案 2 :(得分:1)
如果我们可以假设 ID 只需要在组件内被引用(例如,一个字段和一个标签一起),并且 ID 是什么其他任何地方都无关紧要,只要它是唯一的... uniqid 看起来像应该没问题,但您也可以使用 \Illuminate\Support\Str::random()
作为 ID 的一部分。显然,其中任何一个都会随着每次渲染而改变,我个人也喜欢包含一些有意义的文本(例如 'name_field_'.Str::random()
)。
或者,可以使用单例来生成和跟踪使用的 ID,并确保它们不会被重复使用。类似的东西:
class UniqueIdTracker
{
protected $idTracking = [];
public function __invoke($prefix)
{
$increment = $this->idTracking[$prefix] ?? 0;
$this->idTracking[$prefix]++;
return $prefix . $increment;
}
}
然后用 app(\Namespace\UniqueIdTracker::class)('prefix_')
调用。 (这可以通过将其包装在辅助函数或其他东西中来改进)。
我还注意到 AlpineJS 可能非常适合 OP 的用例,因为脚本可以附加到没有 ID 的元素。