vue-优雅的使用svg


vue-优雅的使用svg

背景

日前,需要开发一个配置数据表单类的框架,需要考虑框架的扩展性,以及使用的便捷性,其中图标类的引入也在考虑之中。

期望实现的效果是在新增一个svg时,仅将svg文件存放到某一个文件夹下,之后使用时通过类似于这种方式即可使用。

思路

  1. 全局注册组件
  2. 使用js读取文件夹下的所有svg导入至项目中

最终使用效果






以下提供 vue3+vite+js 以及 vue2+webpack5+js 的实现方式

实现 - vue3+vite+js

全局注册组件

src/compoments下创建MisIcon.vue







集中存放svg文件

src/assets/svg文件夹下存放所有svg文件

注意:如果需要修改svg的颜色,svg文件中的填充色 fill 必须删除

全局注册组件&全局导入svg

由于Vue3以应用实例方式运行,组件注册需要在main.js中的app挂钩

注:很多东西都需要与main.js中的app挂钩,我以另外的方式重写了,在这里以官方方式进行代码编写

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import MisIcon from "./compoments/MisIcon.vue";
// 配置全局svg导入用的
import 'virtual:svg-icons-register';

const app = createApp(App);
app.component('MisIcon', MisIcon);
app.mount("#app");

全局导入svg

使用 vite-plugin-svg-icons 插件

npm install vite-plugin-svg-icons -S

根目录下的ve.config.js文件中

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";

function resolve(dir) {
  return path.join(__dirname, "./", dir);
}
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    createSvgIconsPlugin({
      // 指定需要缓存的图标文件夹
      iconDirs: [resolve("src/assets/svg")],
      // 指定symbolId格式
      symbolId: "icon-[name]",
    }),
  ]
});

src目录下的main.js

// main.js
// 配置全局svg导入用的插件
import 'virtual:svg-icons-register';

实现 - vue2+webpack+js

全局注册组件

src/compoments下创建MisIcon.vue







集中存放svg文件

  1. src/assets/svg文件夹下存放所有svg文件

    注意:如果需要修改svg的颜色,svg文件中的填充色 fill 必须删除

  2. src/assets 下创建svg.js文件

    // 读取所有svg文件
    const requireAll = requireContext => requireContext.keys().map(requireContext)
    const req = require.context('/src/assets/svg', false, /\.svg$/)
    requireAll(req)
    

全局注册组件并导入svg

// main.js
import '@/assets/svg.js'
import MisIcon from '@/components/MisIcon/icon.vue' // svg组件

// 注册全局插件
Vue.component('mis-icon', MisIcon)

重要的一步 - 配置loader

根目录下的vue.config.js文件中

const path = require('path')

function resolve(dir) {
  return path.join(__dirname, './', dir)
}

module.exports = {
  chainWebpack: config => {
    // svg 规则
    const svgRule = config.module.rule('svg') // 找到原有的svg-loader
    svgRule.uses.clear() // 清除已有的loader, 如果不清除会在原有loader之后再使用当前loader规则
    svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
    svgRule // 添加svg新的loader处理
      .test(/\.svg$/)
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
      })

    // 修改images loader,添加svg处理
    const imagesRule = config.module.rule('images')
    imagesRule.exclude.add(resolve('src/assets/svg'))
    config.module
      .rule('images')
      .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
  }
}

参考链接:

https://www.136.la/nginx/show-209163.html

vue