vue3-09

菜单图标

安装图标依赖

npm install @ant-design/icons-vue

菜单中使用图标

<template>
    <div class="a53">
        <a-layout>
            <a-layout-header></a-layout-header>
            <a-layout>
                <a-layout-sider>
                    <a-menu theme="dark" mode="inline">
                        <a-menu-item :key="1">
                            <template #icon>
                                <highlight-outlined />
                            </template>
                            <router-link to="/a3/student">菜单一</router-link>
                        </a-menu-item>
                        <a-menu-item :key="2">
                            <template #icon>
                                <align-center-outlined />
                            </template>
                            <router-link to="/a3/teacher">菜单二</router-link>
                        </a-menu-item>
                        <a-menu-item :key="3">
                            <template #icon>
                                <strikethrough-outlined />
                            </template>
                            菜单3</a-menu-item>
                        <a-sub-menu :key="4" title="菜单四">
                            <template #icon>
                                <sort-descending-outlined />
                            </template>
                            <a-menu-item :key="41">菜单41</a-menu-item>
                            <a-menu-item :key="42">菜单42</a-menu-item>
                        </a-sub-menu>
                    </a-menu>
                </a-layout-sider>
                <a-layout-content>
                    <router-view></router-view>
                </a-layout-content>
            </a-layout>
        </a-layout>
    </div>
</template>
<script setup lang="ts">
import { HighlightOutlined, AlignCenterOutlined, StrikethroughOutlined } from '@ant-design/icons-vue'
</script>
  • 图标组件没有全局绑定,需要 import 之后才能使用

  • <template #icon></template> 插槽,才能确定图标展示的位置(菜单文字之前)

二次封装图标组件

最终希望用统一的图标组件去使用图标,图标名只是作为一个属性值传递进去,例如:

使用者

<template>
    <a-icon icon="highlight-outlined"></a-icon>
    <a-icon icon="align-center-outlined"></a-icon>
    <a-icon icon="strikethrough-outlined"></a-icon>
    <a-icon icon="sort-descending-outlined"></a-icon>
</template>
<script setup lang="ts">
import AIcon from '../components/AIcon1.vue'
</script>
方法1,使用 vue 组件
<script lang="ts" setup>
import {
  HighlightOutlined,
  AlignCenterOutlined,
  StrikethroughOutlined,
  SortDescendingOutlined,
} from "@ant-design/icons-vue";
const props = defineProps<{ icon: string }>();
</script>
<template>
  <highlight-outlined v-if="icon === 'highlight-outlined'"></highlight-outlined>
  <align-center-outlined
    v-else-if="icon === 'align-center-outlined'"
  ></align-center-outlined>
  <strikethrough-outlined
    v-else-if="icon === 'strikethrough-outlined'"
  ></strikethrough-outlined>
  <sort-descending-outlined
    v-else-if="icon === 'sort-descending-outlined'"
  ></sort-descending-outlined>
</template>
  • 缺点:实现太笨

方法2,使用函数式组件
import { h } from "vue";
import * as Icons from "@ant-design/icons-vue";

interface Module {
  [p: string]: any;
}

// 参数1: 组件属性
const AIcon = (props: { icon: string }) => {
  // console.log(props.icon)
  // console.log(Icons)
  // 参数1: 组件对象
  const im: Module = Icons;
  return h(im[toCamelCase(props.icon)]);
};

export default AIcon;

// 将-分隔的单词转换为大驼峰命名的单词
function toCamelCase(str: string) {
  // highlight-outlined
  return str
    .split("-") // ['highlight', 'outlined']
    .map((e) => e.charAt(0).toUpperCase() + e.slice(1)) // ['Highlight', 'Outlined']
    .join("");
}
/*
Icons 的结构如下
{
  HighlightOutlined: HighlightOutlined组件对象,
  MonitorOutlined: MonitorOutlined组件对象,
  ...
}
*/
  • 需要动态生成标签的时候,可以考虑使用函数式组件

方法3,使用 jsx 组件

首先,安装

npm install @vitejs/plugin-vue-jsx -D

配置 vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), vueJsx()],
});

编写一个 Hi.tsx 组件

export default {
  props: {
    msg: String
  },
  setup(props: { msg: string }) {
    return () => <h5>{props.msg}</h5>
  }
}

然后被其它组件使用

<script setup lang="ts">
import Hi from '../components/Hi'
</script>

<template>
  <Hi msg="Hello,World"></Hi>
</template>

用 jsx 实现图标组件

import * as Icons from '@ant-design/icons-vue'

interface Module {
  [p:string]: any
}

function toCamelCase(str: string) { // highlight-outlined
  return str
    .split("-") // ['highlight', 'outlined']
    .map((e) => e.charAt(0).toUpperCase() + e.slice(1)) // ['Highlight', 'Outlined']
    .join(""); // HighlightOutlined
}

export default {
  props: {
    icon: String
  },
  setup(props: {icon: string}) {
    const im: Module = Icons
    const tag = im[toCamelCase(props.icon)] // 图标组件
    // HighlightOutlined
    return ()=> <tag></tag> // 返回组件标签
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码的翠花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值