vue3 如何获取当前元素的后代元素有class="show"的元素?

无限级菜单
点击每项隐藏或显示每项的后代子菜单

<script setup>
let menus = defineProps({
  'menu': Array
})

let hide = (item) => {
  item['show'] = true
}
</script>

<template>
  <div v-for="(item,index) in menus.menu" style="margin-left: 0.6rem" @click="hide(item)"
       :class="item['show']?'show':'hidden'">
    <div class="item">{{ item['name'] }}
      <div v-if="item['children'].length>0">
        <IMenuItem :menu="item['children']"/>
      </div>
    </div>

  </div>
</template>

<style scoped lang="scss">
.item .hidden {
  visibility: visible;
}

.item .show {
  visibility: hidden;
}
</style>

这是另一个vue文件

<script setup>
import {reactive, ref} from "vue";
import IMenuItem from "@/pages/IMenuItem.vue";

let json = reactive([
  {
    name: '一级',
    children: [
      {
        name: '二级',
        children: [
          {
            name: '三级',
            children: [
              {
                name: '四级',
                children: []
              }
            ]
          }
        ]
      },
      {
        name: '二级',
        children: []
      }
    ]
  },
  {
    name: '一级',
    children: [
      {
        name: '二级',
        children: [
          {
            name: '三级',
            children: [
              {
                name: '四级',
                children: []
              }
            ]
          }
        ]
      },
      {
        name: '二级',
        children: []
      }
    ]
  },
])
</script>

<template>
  <IMenuItem :menu="json"/>
</template>

<style scoped lang="scss">

</style>

以下是我实现的方法

let hide = (item, event) => {
  event.stopPropagation()
  let childMenus = event.target.querySelectorAll(".item");
  if (item['show']) {
    childMenus.forEach(childMenu => {
      childMenu.style.visibility = "visible";
    })
  } else {
    childMenus.forEach(childMenu => {
      childMenu.style.visibility = "hidden";
    })
  }
  item['show'] = !item['show']
}
阅读 1.6k
avatarAI BotBETA

你的代码看起来是基于 Vue 3 的。我注意到你的问题是在获取具有特定类(即 class="show")的后代元素。你提供的代码已经有了基本的菜单显示和隐藏的实现,但是它并没有找到具有 class="show" 的后代元素。

首先,需要指出的是,Vue 3 并不直接提供获取后代元素的 API。在 Vue 中,我们通常通过数据驱动的方式来控制元素的显示和隐藏,而不是直接操作 DOM。

然而,如果你真的需要获取到具有特定类的后代元素,你可以使用 JavaScript 的 DOM API。以下是一个简单的例子:

let menuItem = document.querySelector('.show');
while (menuItem) {
  if (menuItem.classList.contains('item')) {
    console.log(menuItem); // 找到一个有 '.item' 类的 '.show' 后代元素
  }
  menuItem = menuItem.parentNode;
}

这个代码会从页面上找到第一个具有 '.show' 类的元素开始,然后向上查找所有包含 '.item' 类的祖先元素。

然而,这并不是 Vue 的推荐做法。在 Vue 中,我们更倾向于使用 v-ifv-show 指令来控制元素的显示和隐藏,而不是直接操作 DOM。你可以尝试将 v-ifv-show 与 Vue 的响应式数据一起使用,来达到控制菜单显示和隐藏的目的。例如:

<template>
  <div v-for="(item,index) in menus.menu" style="margin-left: 0.6rem" @click="hide(item, $event)" :class="{ show: item['show'] }">
    <div class="item" @click.stop="handleClick($event)">{{ item['name'] }}</div>
    <div v-if="item['children'].length>0" v-show="item['show']">
      <IMenuItem :menu="item['children']"/>
    </div>
  </div>
</template>

<script setup>
let menus = defineProps({ 'menu': Array });
let hide = (item, event) => { item['show'] = !item['show']; };
let handleClick = (event, item) => { event.stopPropagation(); };
</script>

在这个示例中,点击菜单项会切换其 show 属性,并阻止事件冒泡,以防止点击子菜单时父菜单也被触发。

1 个回答

两种方式:
一:纯CSS控制因为你加了scoped,所以你需要.item ::v-deep .hidden这样来设置后代元素
二:增加一个prop,把item.show传入子组件来让子组件设置相应class

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题