我有一个带有 NavBarItem 组件的侧边栏,它接收一个 navItem 对象作为道具,我想在单击链接时将活动状态更改为 true。
<template>
<nav class="mt-2 px-2">
<NavBarItem
@click="setActiveLink(item, _index)"
:item="item"
v-for="(item, _index) in navItems"
:key="item.label"
/>
</nav>
</template>
<script setup>
const setActiveLink = (el, i) => {
// 🤬🤯
}
const navItems = [
{
href: '#',
active: false,
label: 'VehicleBuild',
icon: vehicleTruckCube,
children: [
{
href: '/vehicle-packages',
active: false,
label: 'Paket',
icon: CubeIcon,
children: [],
},
],
}]
</script>
<script setup>
import { RouterLink } from 'vue-router'
import { computed } from 'vue'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue'
import { ChevronDownIcon } from '@heroicons/vue/24/outline'
const props = defineProps({
item: Object,
})
const hasActiveChild = computed(() => {
function hasActiveItem(items) {
return items.some(item => item.active || hasActiveItem(item.children))
}
return hasActiveItem(props.item.children)
})
const emit = defineEmits(['click'])
</script>
<template>
<RouterLink
v-if="!item.children.length"
:class="[
'group flex w-full items-center rounded-md py-2 px-3 text-sm',
'hover:bg-gray-100',
item.active ? 'text-gray-800 font-semibold' : 'text-gray-600 font-medium',
]"
:to="item.href"
@click="emit('click', $event)"
>
<component
:class="[
'w-6 h-6 shrink-0 mr-2 group-hover:text-gray-600',
item.active ? 'text-gray-600' : 'text-gray-400',
]"
:is="item.icon"
v-if="item.icon"
></component>
<span>{{ item.label }}</span>
</RouterLink>
<Disclosure v-else v-slot="{ open }" :default-open="hasActiveChild">
<DisclosureButton
:class="[
'group flex w-full text-left items-center rounded-md py-2 px-3 text-sm',
'hover:bg-gray-100',
open ? 'font-semibold text-gray-800' : 'font-medium text-gray-600',
]"
>
<component
:class="[
'w-6 h-6 shrink-0 mr-2 group-hover:text-gray-600',
open ? 'text-gray-600' : 'text-gray-400',
]"
:is="item.icon"
v-if="item.icon"
></component>
<span class="flex-1">{{ item.label }}</span>
<ChevronDownIcon
:class="['w-4 h-4 shrink-0', open ? '-rotate-180 text-gray-600' : 'text-gray-400']"
/>
</DisclosureButton>
<DisclosurePanel class="ml-4">
<NavBarItem
v-for="(child, index) in item.children"
:item="child"
:key="index"
@click="emit('click', $event)"
/>
</DisclosurePanel>
</Disclosure>
</template>
我试图映射我从 navBarItem 中的发射返回的项目,但没有成功,有人可以帮我吗?
您在安装
navItems
后对<Navbar />
执行的任何突变都不会触发<template />
中的更新,因为数组不是反应性的。
要为其添加反应性,请将其包裹在
ref()
:
const navItems = ref([ /* items here */ ])
在您的
setActiveLink
方法中相应地更新navItems.value
,您将看到模板相应地更新。
文档这里.
重要说明:仅当您想要单独处理每个项目的活动状态时(例如:您希望一次能够拥有多个活动项目),将活动属性存储在每个项目中才有意义。如果
active
状态是互斥的(例如:制作一个项目 active
意味着前一个不再处于活动状态),您 不应该 将活动状态存储在每个项目中。
相反,您设置一个状态变量来保存当前活动项目的
id
。每个项目的isActive
属性是一个computed
,它将项目的id
与状态变量的值进行比较。显然,当将状态变量设置为不同的 id
时,旧的活动项变为非活动状态,因为它的 id
不再等于状态变量的值。