Skip to content

Commit

Permalink
feat: svg 图标自动优化去色 & SvgIcon 组件名称支持类型提示
Browse files Browse the repository at this point in the history
  • Loading branch information
heavenly-zy committed Nov 29, 2024
1 parent 3929278 commit e8c1704
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 16 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ dist
node_modules
.eslintcache
vite.config.*.timestamp*
svg-component-global.d.ts
svg-component.d.ts

# MacOS
.DS_Store
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@
"typescript": "5.6.3",
"unocss": "0.64.1",
"unplugin-auto-import": "0.18.6",
"unplugin-svg-component": "0.10.4",
"unplugin-vue-components": "0.27.5",
"vite": "6.0.1",
"vite-plugin-svg-icons": "2.0.1",
"vite-svg-loader": "5.1.0",
"vitest": "2.1.6",
"vue-tsc": "2.1.10"
Expand Down
Empty file.
20 changes: 11 additions & 9 deletions src/common/components/SvgIcon/index.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<script lang="ts" setup>
import SvgSpritesIcon, { type SvgName } from "~virtual/svg-component"
import { computed } from "vue"
type RemoveIconPrefix<T extends SvgName> = T extends `icon-${infer R}` ? R : T;
export type TSvgIconName = RemoveIconPrefix<SvgName>
interface Props {
prefix?: string
name: string
name: TSvgIconName
}
const props = withDefaults(defineProps<Props>(), {
prefix: "icon"
})
const props = defineProps<Props>()
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
const iconName = computed(() => `icon-${props.name}` as SvgName)
</script>

<template>
<svg class="svg-icon">
<use :href="symbolId" />
</svg>
<SvgSpritesIcon :name="iconName" class="svg-icon" />
</template>

<style lang="scss" scoped>
Expand Down
1 change: 0 additions & 1 deletion src/plugins/svg-icons.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { App } from "vue"
import SvgIcon from "@@/components/SvgIcon/index.vue" // Svg Component
import "virtual:svg-icons-register"

export function installSvgIcons(app: App) {
app.component("SvgIcon", SvgIcon)
Expand Down
3 changes: 2 additions & 1 deletion types/vue-router.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { TSvgIconName } from "@@/components/SvgIcon/index.vue"
import "vue-router"

export {}
Expand All @@ -11,7 +12,7 @@ declare module "vue-router" {
/**
* @description 设置该路由的图标,记得将 svg 导入 src/common/assets/icons
*/
svgIcon?: string
svgIcon?: TSvgIconName
/**
* @description 设置该路由的图标,直接使用 Element Plus 的 Icon(与 svgIcon 同时设置时,svgIcon 将优先生效)
*/
Expand Down
25 changes: 21 additions & 4 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import vue from "@vitejs/plugin-vue"
import vueJsx from "@vitejs/plugin-vue-jsx"
import UnoCSS from "unocss/vite"
import AutoImport from "unplugin-auto-import/vite"
import UnpluginSvgComponent from "unplugin-svg-component/vite"
import { ElementPlusResolver } from "unplugin-vue-components/resolvers"
import Components from "unplugin-vue-components/vite"
import { defineConfig, loadEnv } from "vite"
import { createSvgIconsPlugin } from "vite-plugin-svg-icons"
import svgLoader from "vite-svg-loader"

// Configuring Vite: https://cn.vite.dev/config
Expand Down Expand Up @@ -95,9 +95,26 @@ export default defineConfig(({ mode }) => {
// 将 SVG 文件转化为 Vue 组件
svgLoader({ defaultImport: "url" }),
// 生成 SVG 雪碧图
createSvgIconsPlugin({
iconDirs: [resolve(root, "src/common/assets/icons")],
symbolId: "icon-[dir]-[name]"
// github repo: https://github.com/Jevon617/unplugin-svg-component
UnpluginSvgComponent({
/** 图标所在的目录 */
iconDir: [
resolve(root, "src/common/assets/icons"),
resolve(root, "src/common/assets/icons/preserve-color")
],
/** 是否生成 d.ts 文件,开启 dev server 或更改 iconDir 目录中文件时自动生成对应文件 */
dts: true,
/** 保留原有颜色 SVG 目录(适用于存放多色图标) */
preserveColor: resolve(root, "src/common/assets/icons/preserve-color"),
/** 输出 d.ts 文件的目录 */
dtsDir: resolve(root, "types"),
/** 给每个 svg name 加上前缀 */
prefix: "icon",
/** 自定义生成的组件名,默认值为 "SvgIcon" */
componentName: "SvgSpritesIcon",
/** 控制注入 SVG 元素的方法 */
domInsertionStrategy: "dynamic",
treeShaking: false
}),
// 原子化 CSS
UnoCSS(),
Expand Down

0 comments on commit e8c1704

Please sign in to comment.