当前位置:   article > 正文

【Vue3】elementPlus图标和自定义侧边栏图标_element plus图标

element plus图标

目录

使用elementPlus图标

自定义图标

侧边栏自定义图标的应用

vite+vue3+ts中使用自定义图标


使用elementPlus图标

在项目中引入

npm install @element-plus/icons-vue
  1. import 'element-plus/dist/index.css'
  2. import * as ElementPlusIconsVue from '@element-plus/icons-vue'
  3. // 图标
  4. for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  5. app.component(key, component)
  6. }

方法一(动态使用图标):

  1. <el-icon>
  2. <component :is="menu.meta.icon" class="icon"></component>
  3. </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,没有在项目根目录新建一个即可

  1. const path = require("path");
  2. function resolve (dir) {
  3. return path.join(__dirname, dir);
  4. }
  5. module.exports = {
  6. chainWebpack: config => {
  7. // 清除svg默认配置对./src/icons文件夹的处理
  8. config.module
  9. .rule("svg")
  10. .exclude.add(resolve("src/icons")) // icons存放地(svg放的地方)
  11. .end()
  12. // 添加新的rule处理./src/icons文件夹的svg文件
  13. config.module
  14. .rule("svg-sprite")
  15. .test(/\.svg$/)
  16. .include
  17. .add(resolve("src/icons"))
  18. .end()
  19. .use("svg-sprite-loader")
  20. .loader("svg-sprite-loader")
  21. .options({
  22. symbolId: "icon-[name]",
  23. include: ["src/assets/icons"]
  24. })
  25. .end()
  26. //去除fill
  27. .before("svg-sprite-loader")
  28. .use("svgo-loader")
  29. .loader("svgo-loader")
  30. .options({
  31. plugins: [
  32. { removeAttrs: { attrs: "fill" } }
  33. ]
  34. })
  35. .end()
  36. },
  37. }

5、 创建src/components/svg,封装svg组件

  1. <template>
  2. <div
  3. v-if="External"
  4. :style="styleExternalIcon"
  5. class="svg-external-icon svg-icon"
  6. v-bind="$attrs"
  7. />
  8. <svg v-else :class="svgClass" aria-hidden="true" v-bind="$attrs">
  9. <use :xlink:href="symbolId" />
  10. </svg>
  11. </template>
  12. <script>
  13. // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
  14. import { isExternal } from '@/utils/validate'
  15. import { defineComponent, reactive, ref, computed } from 'vue'
  16. export default defineComponent({
  17. name: 'SvgIcon',
  18. props: {
  19. iconClass: {
  20. type: String,
  21. required: true
  22. },
  23. className: {
  24. type: String,
  25. default: ''
  26. }
  27. },
  28. setup (props) {
  29. const External = computed(() => {
  30. return isExternal(props.iconClass)
  31. })
  32. const symbolId = computed(() => {
  33. return `#icon-${props.iconClass}`
  34. })
  35. const svgClass = computed(() => {
  36. if (props.className) {
  37. return 'svg-icon ' + props.className
  38. } else {
  39. return 'svg-icon'
  40. }
  41. })
  42. const styleExternalIcon = computed(() => {
  43. return {
  44. mask: `url(${props.iconClass}) no-repeat 50% 50%`,
  45. '-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`
  46. }
  47. })
  48. return {
  49. External,
  50. symbolId,
  51. svgClass,
  52. styleExternalIcon,
  53. }
  54. }
  55. })
  56. </script>
  57. <style scoped>
  58. .svg-icon {
  59. width: 1.4em;
  60. height: 1.4em;
  61. margin: 0 0 0 2px;
  62. vertical-align: -0.1em;
  63. fill: currentColor;
  64. overflow: hidden;
  65. }
  66. .svg-external-icon {
  67. background-color: currentColor;
  68. mask-size: cover !important;
  69. display: inline-block;
  70. }
  71. </style>

其中utils/validate.ts

  1. /**
  2. * Created by PanJiaChen on 16/11/18.
  3. */
  4. /**
  5. * @param {string} path
  6. * @returns {Boolean}
  7. */
  8. export function isExternal(path: string) {
  9. const isExternal = /^(https?:|http?:|mailto:|tel:)/.test(path);
  10. return isExternal;
  11. }

6、使用全局注册,这样就不用图标一个一个引入了,创建src/icons/index.ts

  1. import SvgIcon from '@/components/svg/index.vue' // svg component
  2. /**
  3. * 一次性的引入某个文件夹下的所有文件
  4. * require.context(directory, useSubdirectories,regExp)
  5. * 形参:
  6. * directory:需要引入文件的目录
  7. * useSubdirectories:是否查找该目录下的子级目录
  8. * regExp:匹配引入文件的正则表达式
  9. */
  10. const registerSvgIcon = (app: any) => {
  11. app.component('svg-icon', SvgIcon) // 注册全局组件
  12. const req = require.context('./svg', false, /\.svg$/);
  13. const requireAll = (requireContext: any) => requireContext.keys().map(requireContext);
  14. requireAll(req);
  15. }
  16. export default registerSvgIcon;

5、main.ts引入

  1. import registerSvgIcon from "@/icons/index";
  2. const app = createApp(App)
  3. registerSvgIcon(app)

6、页面使用

在所需页面中也需要引入svgIcon组件

<SvgIcon icon-class="yonghu"/>

侧边栏自定义图标的应用

侧边栏使用图标的时候需要判断一下,使用的是自定义图标还是elementPlus图标。

像elementUI图标他每一个图标都是以el-icon开头的,所以只要判断一下图标是否包含‘el-icon’,不包含的就是自定义图标。而elementPlus图标相反,所以我们可以在自定义图标前添加一个标识即可。 

我这里没有使用render进行对图标封装,因为我还没弄明白怎么返回elementPlus图标,所以有大佬如果知道,还请留言指教

重点代码:

  1. <!-- 判断有没有图标并且是否是自定义图标,有就展示,没有则去除icon的位置 -->
  2. <SvgIcon
  3. v-if="
  4. item.meta && item.meta.icon && item.meta.icon.includes('icon-')
  5. "
  6. :icon-class="item.meta.icon"
  7. />
  8. <el-icon v-else>
  9. <component
  10. v-if="item.meta && item.meta.icon"
  11. :is="item.meta.icon"
  12. class="icon"
  13. ></component>
  14. </el-icon>

完整代码:

  1. <template>
  2. <div v-if="!item.meta || !item.meta.hide">
  3. <!-- 一级 -->
  4. <template
  5. v-if="
  6. hasOneShowingChild(item.children, item) &&
  7. (!onlyOneChild.children || onlyOneChild.noShowingChildren) &&
  8. (!item.meta || !item.alwaysShow)
  9. "
  10. >
  11. <app-link v-if="item.meta" :to="item.path">
  12. <el-menu-item
  13. :index="item.children ? item.children[0].path : item.path"
  14. :class="{ 'submenu-title-noDropdown': item.class_true }"
  15. >
  16. <!-- 判断有没有图标并且是否是自定义图标,有就展示,没有则去除icon的位置 -->
  17. <SvgIcon
  18. v-if="
  19. item.meta && item.meta.icon && item.meta.icon.includes('icon-')
  20. "
  21. :icon-class="item.meta.icon"
  22. />
  23. <el-icon v-else>
  24. <component
  25. v-if="item.meta && item.meta.icon"
  26. :is="item.meta.icon"
  27. class="icon"
  28. ></component>
  29. </el-icon>
  30. <template #title>
  31. {{ item.meta.title }}
  32. </template>
  33. </el-menu-item>
  34. </app-link>
  35. </template>
  36. <!-- 二级 -->
  37. <template v-else>
  38. <el-sub-menu ref="subMenu" :index="item.path" popper-append-to-body>
  39. <template #title>
  40. <SvgIcon
  41. v-if="
  42. item.meta && item.meta.icon && item.meta.icon.includes('icon-')
  43. "
  44. :icon-class="item.meta.icon"
  45. />
  46. <el-icon v-else>
  47. <component
  48. v-if="item.meta && item.meta.icon"
  49. :is="item.meta.icon"
  50. class="icon"
  51. ></component>
  52. </el-icon>
  53. <span>{{ item.meta.title }}</span>
  54. </template>
  55. <el-menu-item-group>
  56. <SidebarItem
  57. v-for="v in item.children"
  58. :item="v"
  59. :key="v.path"
  60. :base-path="v.path"
  61. :is-nest="true"
  62. ></SidebarItem>
  63. </el-menu-item-group>
  64. </el-sub-menu>
  65. </template>
  66. </div>
  67. </template>
  68. <script>
  69. import { defineComponent, reactive, ref } from 'vue'
  70. import AppLink from './Link.vue'
  71. import SvgIcon from "@/components/svg/index.vue";
  72. import Item from './item.vue'
  73. export default defineComponent({
  74. name: 'SidebarItem',
  75. components: {
  76. AppLink,
  77. SvgIcon,
  78. Item
  79. },
  80. props: {
  81. item: {
  82. type: Object,
  83. required: true,
  84. },
  85. isNest: {
  86. type: Boolean,
  87. required: false,
  88. },
  89. basePath: {
  90. type: String,
  91. required: true,
  92. },
  93. },
  94. setup () {
  95. const onlyOneChild = ref();
  96. function hasOneShowingChild (children, parent) {
  97. if (!children) {
  98. children = [];
  99. }
  100. const showingChildren = children.filter((item) => {
  101. if (item.meta && item.meta.hide) {
  102. return false;
  103. } else {
  104. // Temp set(will be used if only has one showing child)
  105. onlyOneChild.value = item;
  106. return true;
  107. }
  108. });
  109. // When there is only one child router, the child router is displayed by default
  110. if (showingChildren.length === 1) {
  111. return true;
  112. }
  113. // Show parent if there are no child router to display
  114. if (showingChildren.length === 0) {
  115. onlyOneChild.value = { ...parent, path: '', noShowingChildren: true };
  116. return true;
  117. }
  118. return false;
  119. }
  120. return {
  121. onlyOneChild,
  122. hasOneShowingChild,
  123. }
  124. }
  125. })
  126. </script>
  127. <style lang="scss">
  128. .icon {
  129. font-size: 20px;
  130. }
  131. .submenu-title-noDropdown {
  132. color: #3fa9f5;
  133. }
  134. </style>

vite+vue3+ts中使用自定义图标

1、创建src/icons/svg目录,将自己的图标放入此文件夹内。

2、下载插件

npm i vite-plugin-svg-icons -D

3、vite.config.ts 中的配置插件

  1. import { defineConfig } from 'vite'
  2. import vue from '@vitejs/plugin-vue'
  3. import path from "path";
  4. import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
  5. // https://vitejs.dev/config/
  6. export default defineConfig({
  7. plugins: [
  8. vue(),
  9. createSvgIconsPlugin({
  10. // 指定需要缓存的图标文件夹
  11. iconDirs: [path.resolve(process.cwd(), 'src/icons')],
  12. // 指定symbolId格式
  13. symbolId: 'icon-[dir]-[name]',
  14. }),
  15. ],
  16. })

4、main.ts

import 'virtual:svg-icons-register'

5、 创建src/components/svg,封装svg组件

  1. <template>
  2. <div
  3. v-if="External"
  4. :style="styleExternalIcon"
  5. class="svg-external-icon svg-icon"
  6. v-bind="$attrs"
  7. />
  8. <svg v-else :class="svgClass" aria-hidden="true" v-bind="$attrs">
  9. <use :xlink:href="symbolId" />
  10. </svg>
  11. </template>
  12. <script>
  13. // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
  14. import { isExternal } from '@/utils/validate'
  15. import { defineComponent, reactive, ref, computed } from 'vue'
  16. export default defineComponent({
  17. name: 'SvgIcon',
  18. props: {
  19. iconClass: {
  20. type: String,
  21. required: true
  22. },
  23. className: {
  24. type: String,
  25. default: ''
  26. }
  27. },
  28. setup (props) {
  29. const External = computed(() => {
  30. return isExternal(props.iconClass)
  31. })
  32. const symbolId = computed(() => {
  33. return `#icon-${props.iconClass}`
  34. })
  35. const svgClass = computed(() => {
  36. if (props.className) {
  37. return 'svg-icon ' + props.className
  38. } else {
  39. return 'svg-icon'
  40. }
  41. })
  42. const styleExternalIcon = computed(() => {
  43. return {
  44. mask: `url(${props.iconClass}) no-repeat 50% 50%`,
  45. '-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`
  46. }
  47. })
  48. return {
  49. External,
  50. symbolId,
  51. svgClass,
  52. styleExternalIcon,
  53. }
  54. }
  55. })
  56. </script>
  57. <style scoped>
  58. .svg-icon {
  59. width: 1.4em;
  60. height: 1.4em;
  61. margin: 0 0 0 2px;
  62. vertical-align: -0.1em;
  63. fill: currentColor;
  64. overflow: hidden;
  65. }
  66. .svg-external-icon {
  67. background-color: currentColor;
  68. mask-size: cover !important;
  69. display: inline-block;
  70. }
  71. </style>

 其中utils/validate.ts

  1. /**
  2. * Created by PanJiaChen on 16/11/18.
  3. */
  4. /**
  5. * @param {string} path
  6. * @returns {Boolean}
  7. */
  8. export function isExternal(path: string) {
  9. const isExternal = /^(https?:|http?:|mailto:|tel:)/.test(path);
  10. return isExternal;
  11. }

6、全局注册mian.ts

  1. import 'virtual:svg-icons-register'
  2. import SvgIcon from "@/components/svg/index.vue";
  3. const app = createApp(App)
  4. app.use(store)
  5. .use(router)
  6. .use(ElementPlus)
  7. .component('svg-icon', SvgIcon)
  8. .mount("#app");

7、页面使用

 在所需页面中也需要引入svgIcon组件

<SvgIcon icon-class="yonghu"/>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/113187
推荐阅读
相关标签
  

闽ICP备14008679号