Смена иконки naiveui menu по клику

Рейтинг: 0Ответов: 1Опубликовано: 14.01.2023

Пробую сделать смену темы с помощью кнопки в меню и хочу менять иконку BookmarkOutline на какую либо другую в из @vicons/ionicons5.

Сами иконки генерируются с помощью h().

Клик по кнопке меню ловлю по update:value и потом меняю this.theme. Хотелось бы менять иконку в зависимости от значения this.theme

<template>
  <n-space vertical>
    <n-switch v-model:value="collapsed" />
    <n-layout has-sider>
      <n-layout-sider
        bordered
        collapse-mode="width"
        :collapsed-width="64"
        :width="240"
        :collapsed="collapsed"
        show-trigger
        @update:value="handleClick"
        @collapse="collapsed = true"
        @expand="collapsed = false"
      >
        <n-menu
          :collapsed="collapsed"
          :collapsed-width="64"
          :collapsed-icon-size="22"
          :options="menuOptions"
          :render-label="renderMenuLabel"
          :render-icon="renderMenuIcon"
          :expand-icon="expandIcon"
        />
      </n-layout-sider>
      <n-layout>
        <span>Content</span>
      </n-layout>
    </n-layout>
  </n-space>
</template>

<script>
import { h, ref, defineComponent } from "vue";
import { NIcon } from "naive-ui";
import { BookmarkOutline, CaretDownOutline } from "@vicons/ionicons5";

const menuOptions = [
  {
    label: "LABEL NAME",
    key: "key-name",
  }
];

export default defineComponent({
  methods: {
    handleClick: function (key) {
      if (key === 'key-name')
        this.theme = !this.theme
    }
  },
  setup() {
    return {
      theme: ref(true),
      menuOptions,
      collapsed: ref(true),
      renderMenuLabel(option) {
        if ("href" in option) {
          return h("a", { href: option.href, target: "_blank" }, [
            option.label
          ]);
        }
        return option.label;
      },
      renderMenuIcon(option) {
        if (option.key === "key-name")
          return h(NIcon, null, { default: () => h(BookmarkOutline) });
      },
      expandIcon() {
        return h(NIcon, null, { default: () => h(CaretDownOutline) });
      }
    };
  }
});
</script>

Ответы

▲ 0Принят

В связи с тем что тема ставится у меня глобально, то я в итоге пришел к решению прокинуть данные темы в Pinia, а саму "иконку" вынести в отдельный компонент и подставить вместо нее этот компонент, где я рендерю нужную иконку в зависимости от стейта.

Вышло вот так:

<template>
  <component :is="config.theme === 'dark' ? 'MoonOutline' : 'SunnyOutline'"/>
</template>

<script>
import { defineComponent } from 'vue'
import { MoonOutline, SunnyOutline } from '@vicons/ionicons5'
import { useConfigStore } from '../../store'

export default defineComponent({
  components: { MoonOutline, SunnyOutline },
  setup () {
    const config = useConfigStore()
    return { config }
  },
})
</script>

И этот компонент уже был использован вместо самой иконки (в вопросе она - BookmarkOutline)