我有一个可能在页面上显示两次的组件。加载页面后,我想执行一个脚本,显示或隐藏组件的某些元素。我目前拥有的代码如下:
<script>
revealCurrentArticle();
function revealCurrentArticle() {
const path = window.location.pathname;
const currentLi = document.querySelector(`[data-path="${path}"]`);
if (currentLi === null) {
return;
}
let parent: HTMLElement | null | undefined = currentLi.parentElement;
while(parent) {
if (parent.nodeName.toLowerCase() !== "ul") {
break;
}
parent.classList.remove('hidden');
parent = parent.parentElement?.parentElement;
}
}
</script>
问题在于:
const currentLi = document.querySelector(`[data-path="${path}"]`);
查找元素,但不一定是属于该组件实例的元素。
我知道我可以使用document.querySelectorAll
,但这会使我的组件意识到它可能在页面上显示多次,而我不希望这样。是否有任何方法可以确保currentLi
始终包含对该组件实例中的HTML元素的引用?
您可以在组件脚本中为组件的每次使用生成一个唯一的值。然后,使用define:vars
将其传递给客户端脚本,并将其用作类&
例如:
---
const id = Math.random().toString(36).slice(2, 11)
---
<div class={id}></div>
<script define:vars={{id}}>
console.log(document.querySelector(`.${id}`))
</script>
路径限制
对于可以包含同一实例的多个组件的页面,路径应该是相同的。
使用定义:var
可以使用define:vars,但这会导致每个实例都重复脚本,因为它将vars转换为const。
以下建议的解决方案可以单独基于js,并且可以导致所有组件实例的单个脚本
使用url搜索参数
深层链接的常用方式其中引用同一页面内的不同项目是使用查询搜索参数,可以引用你想要深度链接的元素的id。
示例path/?modal=image1
你的例子有点抽象,为了更容易理解,让我们想象一个有多个图像的页面,每个图像都有一个可以打开模态的组件。
这是一个来自astro组件的片段
---
const assetname = ... unique instance name
---
<div class="container panzoom" data-name={assetname} >
<img src={asseturl} />
<PanZoomModal url={asseturl} />
</div>
这是一个检查url搜索参数并获取特定参数的示例函数在本例中称为modal,如path/?modal=image1
在这种情况下,发送一个事件来触发打开相应的模式,该模式已经针对具有正确data-name
属性的唯一实例
const params = new URL(location.href).searchParams;
const modal_name = params.get('modal');
if(modal_name){
const container = document.querySelector(`.container.panzoom[data-name="${modal_name}"]`)
if(container){
event(container,"init")
}
}
参考例子这个行为的完整例子可以在这里找到
检查url参数https://github.com/MicroWebStacks/astro-big-doc/blob/09391234d1ab1a72930f9059448a6d72520191b1/src/components/panzoom.js#L26
唯一数据属性https://github.com/MicroWebStacks/astro-big-doc/blob/09391234d1ab1a72930f9059448a6d72520191b1/src/components/panzoom.astro#L23