赞
踩
目录
在项目中引入
npm install @element-plus/icons-vue
- import 'element-plus/dist/index.css'
- import * as ElementPlusIconsVue from '@element-plus/icons-vue'
-
- // 图标
- for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
- app.component(key, component)
- }
方法一(动态使用图标):
- <el-icon>
- <component :is="menu.meta.icon" class="icon"></component>
- </el-icon>
方法二(直接使用图标):
然后直接使用
<el-icon><Expand /></el-icon>
具体详细图标可查看:https://element-plus.gitee.io/zh-CN/component/icon.html
1、创建src/icons/svg目录,将自己的图标放入此文件夹内。
2、npm install svg-sprite-loader --save-dev (实现加载svg自定义组件)
npm i svgo@1.0.5 svgo-loader@2.2.0 --save-dev (自动去除图标中的fill)
3、配置vue.config.js,没有在项目根目录新建一个即可
- const path = require("path");
- function resolve (dir) {
- return path.join(__dirname, dir);
- }
-
- module.exports = {
- chainWebpack: config => {
- // 清除svg默认配置对./src/icons文件夹的处理
- config.module
- .rule("svg")
- .exclude.add(resolve("src/icons")) // icons存放地(svg放的地方)
- .end()
-
- // 添加新的rule处理./src/icons文件夹的svg文件
- config.module
- .rule("svg-sprite")
- .test(/\.svg$/)
- .include
- .add(resolve("src/icons"))
- .end()
- .use("svg-sprite-loader")
- .loader("svg-sprite-loader")
- .options({
- symbolId: "icon-[name]",
- include: ["src/assets/icons"]
- })
- .end()
- //去除fill
- .before("svg-sprite-loader")
- .use("svgo-loader")
- .loader("svgo-loader")
- .options({
- plugins: [
- { removeAttrs: { attrs: "fill" } }
- ]
- })
- .end()
- },
- }
5、 创建src/components/svg,封装svg组件
- <template>
- <div
- v-if="External"
- :style="styleExternalIcon"
- class="svg-external-icon svg-icon"
- v-bind="$attrs"
- />
- <svg v-else :class="svgClass" aria-hidden="true" v-bind="$attrs">
- <use :xlink:href="symbolId" />
- </svg>
- </template>
-
- <script>
- // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
- import { isExternal } from '@/utils/validate'
- import { defineComponent, reactive, ref, computed } from 'vue'
-
- export default defineComponent({
- name: 'SvgIcon',
- props: {
- iconClass: {
- type: String,
- required: true
- },
- className: {
- type: String,
- default: ''
- }
- },
- setup (props) {
- const External = computed(() => {
- return isExternal(props.iconClass)
- })
- const symbolId = computed(() => {
- return `#icon-${props.iconClass}`
- })
- const svgClass = computed(() => {
- if (props.className) {
- return 'svg-icon ' + props.className
- } else {
- return 'svg-icon'
- }
- })
- const styleExternalIcon = computed(() => {
- return {
- mask: `url(${props.iconClass}) no-repeat 50% 50%`,
- '-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`
- }
- })
-
- return {
- External,
- symbolId,
- svgClass,
- styleExternalIcon,
- }
- }
- })
- </script>
-
- <style scoped>
- .svg-icon {
- width: 1.4em;
- height: 1.4em;
- margin: 0 0 0 2px;
- vertical-align: -0.1em;
- fill: currentColor;
- overflow: hidden;
- }
-
- .svg-external-icon {
- background-color: currentColor;
- mask-size: cover !important;
- display: inline-block;
- }
- </style>
其中utils/validate.ts
- /**
- * Created by PanJiaChen on 16/11/18.
- */
-
- /**
- * @param {string} path
- * @returns {Boolean}
- */
- export function isExternal(path: string) {
- const isExternal = /^(https?:|http?:|mailto:|tel:)/.test(path);
- return isExternal;
- }
6、使用全局注册,这样就不用图标一个一个引入了,创建src/icons/index.ts
- import SvgIcon from '@/components/svg/index.vue' // svg component
-
- /**
- * 一次性的引入某个文件夹下的所有文件
- * require.context(directory, useSubdirectories,regExp)
- * 形参:
- * directory:需要引入文件的目录
- * useSubdirectories:是否查找该目录下的子级目录
- * regExp:匹配引入文件的正则表达式
- */
-
- const registerSvgIcon = (app: any) => {
- app.component('svg-icon', SvgIcon) // 注册全局组件
-
- const req = require.context('./svg', false, /\.svg$/);
- const requireAll = (requireContext: any) => requireContext.keys().map(requireContext);
- requireAll(req);
- }
-
- export default registerSvgIcon;
5、main.ts引入
- import registerSvgIcon from "@/icons/index";
- const app = createApp(App)
- registerSvgIcon(app)
6、页面使用
在所需页面中也需要引入svgIcon组件
<SvgIcon icon-class="yonghu"/>
侧边栏使用图标的时候需要判断一下,使用的是自定义图标还是elementPlus图标。
像elementUI图标他每一个图标都是以el-icon开头的,所以只要判断一下图标是否包含‘el-icon’,不包含的就是自定义图标。而elementPlus图标相反,所以我们可以在自定义图标前添加一个标识即可。
我这里没有使用render进行对图标封装,因为我还没弄明白怎么返回elementPlus图标,所以有大佬如果知道,还请留言指教
重点代码:
- <!-- 判断有没有图标并且是否是自定义图标,有就展示,没有则去除icon的位置 -->
- <SvgIcon
- v-if="
- item.meta && item.meta.icon && item.meta.icon.includes('icon-')
- "
- :icon-class="item.meta.icon"
- />
- <el-icon v-else>
- <component
- v-if="item.meta && item.meta.icon"
- :is="item.meta.icon"
- class="icon"
- ></component>
- </el-icon>
完整代码:
- <template>
- <div v-if="!item.meta || !item.meta.hide">
- <!-- 一级 -->
- <template
- v-if="
- hasOneShowingChild(item.children, item) &&
- (!onlyOneChild.children || onlyOneChild.noShowingChildren) &&
- (!item.meta || !item.alwaysShow)
- "
- >
- <app-link v-if="item.meta" :to="item.path">
- <el-menu-item
- :index="item.children ? item.children[0].path : item.path"
- :class="{ 'submenu-title-noDropdown': item.class_true }"
- >
- <!-- 判断有没有图标并且是否是自定义图标,有就展示,没有则去除icon的位置 -->
- <SvgIcon
- v-if="
- item.meta && item.meta.icon && item.meta.icon.includes('icon-')
- "
- :icon-class="item.meta.icon"
- />
- <el-icon v-else>
- <component
- v-if="item.meta && item.meta.icon"
- :is="item.meta.icon"
- class="icon"
- ></component>
- </el-icon>
-
- <template #title>
- {{ item.meta.title }}
- </template>
- </el-menu-item>
- </app-link>
- </template>
- <!-- 二级 -->
- <template v-else>
- <el-sub-menu ref="subMenu" :index="item.path" popper-append-to-body>
- <template #title>
- <SvgIcon
- v-if="
- item.meta && item.meta.icon && item.meta.icon.includes('icon-')
- "
- :icon-class="item.meta.icon"
- />
- <el-icon v-else>
- <component
- v-if="item.meta && item.meta.icon"
- :is="item.meta.icon"
- class="icon"
- ></component>
- </el-icon>
- <span>{{ item.meta.title }}</span>
- </template>
- <el-menu-item-group>
- <SidebarItem
- v-for="v in item.children"
- :item="v"
- :key="v.path"
- :base-path="v.path"
- :is-nest="true"
- ></SidebarItem>
- </el-menu-item-group>
- </el-sub-menu>
- </template>
- </div>
- </template>
-
- <script>
- import { defineComponent, reactive, ref } from 'vue'
- import AppLink from './Link.vue'
- import SvgIcon from "@/components/svg/index.vue";
- import Item from './item.vue'
-
- export default defineComponent({
- name: 'SidebarItem',
- components: {
- AppLink,
- SvgIcon,
- Item
- },
- props: {
- item: {
- type: Object,
- required: true,
- },
- isNest: {
- type: Boolean,
- required: false,
- },
- basePath: {
- type: String,
- required: true,
- },
- },
- setup () {
- const onlyOneChild = ref();
-
- function hasOneShowingChild (children, parent) {
- if (!children) {
- children = [];
- }
- const showingChildren = children.filter((item) => {
- if (item.meta && item.meta.hide) {
- return false;
- } else {
- // Temp set(will be used if only has one showing child)
- onlyOneChild.value = item;
- return true;
- }
- });
-
- // When there is only one child router, the child router is displayed by default
- if (showingChildren.length === 1) {
- return true;
- }
-
- // Show parent if there are no child router to display
- if (showingChildren.length === 0) {
- onlyOneChild.value = { ...parent, path: '', noShowingChildren: true };
- return true;
- }
-
- return false;
- }
-
- return {
- onlyOneChild,
- hasOneShowingChild,
- }
- }
- })
- </script>
-
- <style lang="scss">
- .icon {
- font-size: 20px;
- }
-
- .submenu-title-noDropdown {
- color: #3fa9f5;
- }
- </style>
1、创建src/icons/svg目录,将自己的图标放入此文件夹内。
2、下载插件
npm i vite-plugin-svg-icons -D
3、vite.config.ts 中的配置插件
- import { defineConfig } from 'vite'
- import vue from '@vitejs/plugin-vue'
- import path from "path";
- import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
-
- // https://vitejs.dev/config/
- export default defineConfig({
- plugins: [
- vue(),
- createSvgIconsPlugin({
- // 指定需要缓存的图标文件夹
- iconDirs: [path.resolve(process.cwd(), 'src/icons')],
- // 指定symbolId格式
- symbolId: 'icon-[dir]-[name]',
- }),
- ],
- })
4、main.ts
import 'virtual:svg-icons-register'
5、 创建src/components/svg,封装svg组件
- <template>
- <div
- v-if="External"
- :style="styleExternalIcon"
- class="svg-external-icon svg-icon"
- v-bind="$attrs"
- />
- <svg v-else :class="svgClass" aria-hidden="true" v-bind="$attrs">
- <use :xlink:href="symbolId" />
- </svg>
- </template>
-
- <script>
- // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
- import { isExternal } from '@/utils/validate'
- import { defineComponent, reactive, ref, computed } from 'vue'
-
- export default defineComponent({
- name: 'SvgIcon',
- props: {
- iconClass: {
- type: String,
- required: true
- },
- className: {
- type: String,
- default: ''
- }
- },
- setup (props) {
- const External = computed(() => {
- return isExternal(props.iconClass)
- })
- const symbolId = computed(() => {
- return `#icon-${props.iconClass}`
- })
- const svgClass = computed(() => {
- if (props.className) {
- return 'svg-icon ' + props.className
- } else {
- return 'svg-icon'
- }
- })
- const styleExternalIcon = computed(() => {
- return {
- mask: `url(${props.iconClass}) no-repeat 50% 50%`,
- '-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`
- }
- })
-
- return {
- External,
- symbolId,
- svgClass,
- styleExternalIcon,
- }
- }
- })
- </script>
-
- <style scoped>
- .svg-icon {
- width: 1.4em;
- height: 1.4em;
- margin: 0 0 0 2px;
- vertical-align: -0.1em;
- fill: currentColor;
- overflow: hidden;
- }
-
- .svg-external-icon {
- background-color: currentColor;
- mask-size: cover !important;
- display: inline-block;
- }
- </style>
其中utils/validate.ts
- /**
- * Created by PanJiaChen on 16/11/18.
- */
-
- /**
- * @param {string} path
- * @returns {Boolean}
- */
- export function isExternal(path: string) {
- const isExternal = /^(https?:|http?:|mailto:|tel:)/.test(path);
- return isExternal;
- }
6、全局注册mian.ts
- import 'virtual:svg-icons-register'
- import SvgIcon from "@/components/svg/index.vue";
-
- const app = createApp(App)
- app.use(store)
- .use(router)
- .use(ElementPlus)
- .component('svg-icon', SvgIcon)
- .mount("#app");
7、页面使用
在所需页面中也需要引入svgIcon组件
<SvgIcon icon-class="yonghu"/>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。