50 菜单激活功能 - udo-bit/naive_admin_pro GitHub Wiki

目标

完成菜单激活功能开发

开发

为了方便我们在后续的开发中去使用我们的状态信息,所以我们采用依赖注入的方式进行开发。
我们这里会带大家使用vueuse中的 createInjectionState方法进行创建依赖注入。
首先我们先来在composable下创建一个menu-state.ts文件用于存放我们的数据状态。

import type { Ref } from 'vue'
import { loginRoute } from '~/routes/router-guard'

export interface MenuState {
  active: string
}

export interface MenuStateFn {
  active: Ref<string>
  updateActive: (active: string) => void
}

// 1.因为createInjectionState要求我们传入的是一个方法,所以我们先在上边定义一个方法,
// 写法我们使用类似setup的写法即可
const menuStateFn = (): MenuStateFn => {
  const route = useRoute()
  // 先定义类型
  const state = reactive<MenuState>({
    active: '',
  })

  // 创建更新方法
  const updateActive = (active: string) => {
    state.active = active
  }

  // 当组件渲染完成后我们再进行执行watch监听
  tryOnMounted(() => {
    // 监听路由地址的变化
    watch(() => route.path, () => {
      // 我们排除路由为登录的时候的路由
      if (route.path !== loginRoute)
        updateActive(route.path)
    })
  })

  // 最后我们解构抛出
  return {
    ...toRefs(state),
    updateActive,
  }
}

// 创建依赖注入,这个方法返回的是一个数组,一个是注入函数,第二个是获取注入数据的函数,
const [useMenuStateProvider, useMenuState] = createInjectionState(menuStateFn)

// 由于第二个注入函数可能是一个undefined,所以我们再进行一次封装保证百分百能拿到值。
export const useMenuStateInject = (): MenuStateFn => {
  return useMenuState() ?? {
    active: ref(''),
    updateActive: (_path: string) => {},
  }
}
// 抛出注入
export {
  useMenuStateProvider,
}

然后在App.vue中增加如下:

<script setup lang="ts">
useMenuStateProvider()
</script>

然后我们在base-layout中进行测试

<script setup lang="ts">
  // 这里我们发现没有类型提示,所以我们要去增加类型提示在menu-state.ts中
const { active } = useMenuStateInject()
</script>

<template>
  <MixLayout
      v-if="layout.layout === 'mix'"
      v-model:collapsed="layout.collapsed"
      :logo="layout.logo"
      :title="layout.title"
      :active="active"
      :options="menuOptions"
      :show-sider-trigger="layout.showSiderTrigger"
      :sider-width="layout.siderWidth"
      :sider-collapsed-width="layout.siderCollapsedWidth"
    >
      <template #headerRight>
        <RightContent />
      </template>
      <router-view />
    </MixLayout>
</template>

最后我们刷新页面测试

⚠️ **GitHub.com Fallback** ⚠️