vue 组件在兄弟姐妹中检测自己的索引

Posted

技术标签:

【中文标题】vue 组件在兄弟姐妹中检测自己的索引【英文标题】:vue component detect own index among siblings 【发布时间】:2021-06-23 17:28:17 【问题描述】:

假设我有一些具有这种关系的 Vue 组件。 CompA 使用插槽。

<CompA>
  <CompB />
  <CompB />
  <CompC />
</CompA>

如果我想知道这些是哪个编号的兄弟,我可以像这样硬编码:

<CompA>
  <CompB i="0" />
  <CompB i="1" />
  <CompC i="2" />
</CompA>

...同时在 CompBCompC 的定义上定义 i 属性。

这些组件是否有任何方法可以自动检测其自己的索引在属于其父级的兄弟姐妹列表中是什么,这样我就不需要将这些索引硬编码为道具?可能使用computed 选项的东西?

特定于 Vue 3 的答案是可以的。

编辑

这里的用例是用于构建符合 ARIA 规范的可重用小部件,其中 ARIA 属性需要引用唯一 ID。

例子:

  <TabContainer tabsWidgetUnique="Tabswidget-1">
      <template v-slot:buttons=" slotProps ">
        <TabButton :index="0" :slotProps="slotProps">Button A</TabButton>
        <TabButton :index="1" :slotProps="slotProps">Button B </TabButton>
        <TabButton :index="2" :slotProps="slotProps">Button C </TabButton>
      </template>
      <template v-slot:panels=" slotProps ">
        <TabPanel :index="0" :slotProps="slotProps"> Panel A </TabPanel>
        <TabPanel :index="1" :slotProps="slotProps"> Panel B </TabPanel>
        <TabPanel :index="2" :slotProps="slotProps"> Panel C </TabPanel>
      </template>
    </TabContainer>

在这种情况下,我手动设置每个索引,以便在组件中我可以说:

<template>
  <div
    class="tab-panel"
    v-show="index === activeTab"
    tabindex="0"
    :id="tabsWidgetUnique + '-panel-' + index"
    :aria-labelledby="tabsWidgetUnique + '-button-' + index"
  >
    <slot />
  </div>
</template>

【问题讨论】:

答案应该是否定的,但更重要的是,为什么需要索引? 这里的用例是设置元素之间的关系以符合 aria 模式。 IE 一个 aria 选项卡模式需要由 aria-controlsaria-labelledby 引用的唯一 ID。因此,我将编辑我的示例以更明确地说明这一点,但想法是一个容器的第一个孩子将与另一个容器的第一个孩子相关联,依此类推。 【参考方案1】:

我无法直接回答您的问题,但我可以为您提供一种不同的、更实用的方法。

<template>
  <TabContaier :data="tabData" :widget="1" />
</template>
<script>
 data() 
   return 
     tabData: 
        buttons: [
           id: 1, label: Button A,
           id: 2, label: Button B,
        ],
        panels: [
           id: 1, content: "<h1>Title 1</h1><p>your content...</p>",
           id: 2, content: "<h1>Title 2</h1><p>your content...</p>",
        ]
      
   
 
</script>

Tab.vue

<template>
  <div class="tab-container">
    <div class="buttons">
      <TabButton
        v-for="button in tabData.buttons"
        :key="button.id"
        @click="activeTab = button.id"
      > button.label </TabButton>
    </div>
    <div class="pabels">
      <TabPanel
        v-for="panel in tabData.panels"
        :key="panel.id"
        :class="'is-visible': activeTab == pabel.id"
        :content="panel.content"
      >
    </div>
  </div>
</template>

<script>
 data() 
   props: 
     tabData: 
       type: Object,
       default: 
     ,
     widget: 
       type: Number,
       default: null
     
   ,
   return 
     avtiveTab: 1
   
 
</script>

TabPabel.vue

<div class="panel" v-html="content"></div>

如果您有任何问题,请告诉我。

【讨论】:

如果面板,而不是容器一个简单的字符串,需要包含 HTML 元素或其他 vue 组件怎么办?这就是为什么在我的原型中我让它们使用插槽。【参考方案2】:

如果您没有在子组件中将传递的属性声明为 prop,它将包含在 $attrs 属性中,例如:

this.$attrs.i

在选项 API 或类似的组合中:

setup(props,attrs)
  //then here you could use attrs.i

【讨论】:

以上是关于vue 组件在兄弟姐妹中检测自己的索引的主要内容,如果未能解决你的问题,请参考以下文章

查询列出所有分层的父母和兄弟姐妹及其孩子,但不列出自己的孩子

在 React 中单击组件时向兄弟姐妹添加类

vue兄弟组件之间方法调用

致初入职场的兄弟姐妹

vue 调用兄弟组件方法怎么做

从另一个组件更新组件状态的最简单方法是啥?可以说组件是兄弟姐妹吗?