可参考:
未来必热:SVG Sprites技术介绍
懒人神器:svg-sprite-loader实现自己的Icon组件
在Vue3项目中使用svg-sprite-loader

前置知识

页面中,虽然可以通过如下方式使用img标签,来引入svg图标。但是,如果这个路径很长,也是比较麻烦的。

<img src="./svg/icon.svg" />

svg里面可以文档中先定义Symbol然后svg使用时候,只须通过标识引用指定svg即可,Symbol放置顺序不一定要在最前面,案例如下:
在这里插入图片描述

<html>

<head>
  <meta charset="utf-8">
  <title>SVG Sprite使用</title>
  <style>
    li {
      font-size: 14px;
      margin-top: 5px;
      color: #369;
    }

    .webicon {
      width: 16px;
      height: 16px;
      margin-right: 5px;
      vertical-align: -2px;
      fill: #369;
    }
  </style>
</head>

<body>
  <div style="display: none;"><svg>
      <symbol id="liwu" viewBox="-80 -72.013 160 144.025">
        <path
          d="M-71.949-16.039h55.974v-55.974h-55.974V-16.039z M16.102-16.039h55.975v-55.974H16.102V-16.039z M-80,32.013h64.025v-40H-80V32.013z M80,32.013v-40H16.102v40H80z M-7.923,32.013H8.051V-72.013H-7.923V32.013z M16.102,39.936 h-32.077v24.025h32.077V39.936z M64.025,39.936h-40l15.719,32.077h24.281V39.936z M-23.898,39.936h-40v32.077H-40L-23.898,39.936z"
          transform="matrix(1 0 0 -1 0 0)"></path>
      </symbol>
      <symbol id="qianbi" viewBox="-79.5 -79.5 159 159">
        <path
          d="M79.5,32.802l-93.538-93.538l-46.699,46.699L32.802,79.5L79.5,32.802z M-79.5-32.802L-32.802-79.5H-79.5 V-32.802z"
          transform="matrix(1 0 0 -1 0 0)"></path>
      </symbol>
      <symbol id="shangchuan" viewBox="-73.623 -78.055 147.245 156.11">
        <path
          d="M0.069,32.482L64.48-32.205H36.915v-45.85h-73.83l-0.139,45.85h-27.15L0.069,32.482z M73.623,78.055V59.632 H-73.623v18.423H73.623z"
          transform="matrix(1 0 0 -1 0 0)"></path>
      </symbol>
    </svg></div>
  <h3>SVG Sprite使用示意</h3>
  <ul>
    <li><svg class="webicon">
        <use xlink:href="#qianbi"></use>
      </svg>编辑信息</li>
    <li><svg class="webicon">
        <use xlink:href="#liwu"></use>
      </svg>兑换礼物</li>
    <li><svg class="webicon">
        <use xlink:href="#shangchuan"></use>
      </svg>上传文件</li>
  </ul>
  </div>
</body>

</html>

vue3+vite自定义svg图标组件

可参考:Vue3后台管理系统(四)SVG图标

1、安装 vitepluginsvg-icons

npm i fast-glob@3.2.11 -D
npm i vite-plugin-svg-icons@2.0.1 -D

2、创建图标文件夹

src/assets文件夹新建icons文件夹用于存放下载的 SVG 图标
在这里插入图片描述

3、vite.config.js 插件配置

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/assets/icons')],
      // 指定symbolId格式
      symbolId: 'icon-[dir]-[name]',
    })
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  }
})

4、SvgIcon组件封装

<!--src/components/SvgIcon/index.vue-->
<template>
  <svg
      aria-hidden="true"
      class="svg-icon"
      :style="'width:' + size + ';height:' + size"
  >
    <use :xlink:href="symbolId" :fill="color"/>
  </svg>
</template>
 
<script setup lang="ts">
import {computed} from 'vue';
 
const props = defineProps({
  prefix: {
    type: String,
    default: 'icon'
  },
  iconClass: {
    type: String,
    required: false
  },
  color: {
    type: String
  },
  size: {
    type: String,
    default: '1em'
  }
});
 
const symbolId = computed(() => `#${props.prefix}-${props.iconClass}`);
</script>
 
<style scoped>
.svg-icon {
  overflow: hidden;
  fill: currentColor;
}
</style>

5、main.js 引入注册脚本

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

import router from '@/router'
import store from '@/store'

// 不知道这个东西是哪来的,但是没它的话,html下面就没有那个Symbol定义
import 'virtual:svg-icons-register';

import SvgIcon from '@/components/SvgIcon/index.vue'


const app = createApp(App)
app.use(router)
app.use(store)

// 注册全局组件
app.component('SvgIcon',SvgIcon)

app.mount('#app')

6、Home.vue中使用SvgIcon组件

<template>
    home
    <svg-icon icon-class="tree" size="40px"/>
    <svg-icon icon-class="tree2" size="50px"/>
</template>

<script setup>

</script>

<style lang="scss">

</style>

在这里插入图片描述

7、图标选择器

IconSelect.vue

src/components文件夹新建IconSelect文件夹,并在IconSelect文件夹新建index.vue

<template>
    <div class="icon-select">
      <el-input
        v-model="iconName"
        clearable
        placeholder="输入图标名称"
        @clear="filterIcons"
        @input="filterIcons"
      >
        <template #suffix><i class="el-icon-search el-input__icon" /></template>
      </el-input>
      <div class="icon-select__list">
        <div
          v-for="(item, index) in iconList"
          :key="index"
          @click="selectedIcon(item)"
        >
          <svg-icon
            color="#999"
            :icon-class="item"
            style="height: 30px; width: 16px; margin-right: 5px"
          />
          <span>{{ item }}</span>
        </div>
      </div>
    </div>
  </template>
   
  <script setup>
  import { ref } from 'vue';
  import SvgIcon from '@/components/SvgIcon/index.vue';
   
  const icons = [] ;
  const modules = import.meta.glob('../../assets/icons/*.svg');
  for (const path in modules) {
    const p = path.split('assets/icons/')[1].split('.svg')[0];
    icons.push(p);
  }
  const iconList = ref(icons);
   
  const iconName = ref('');
   
  const emit = defineEmits(['selected']);
   
  function filterIcons() {
    iconList.value = icons;
    if (iconName.value) {
      iconList.value = icons.filter(item => item.indexOf(iconName.value) !== -1);
    }
  }
   
  function selectedIcon(name) {
    emit('selected', name);
    document.body.click();
  }
   
  function reset() {
    iconName.value = '';
    iconList.value = icons;
  }
   
  defineExpose({
    reset
  });
  </script>
   
  <style lang="scss" scoped>
  .icon-select {
    width: 100%;
    padding: 10px;
   
    &amp;__list {
      height: 200px;
      overflow-y: scroll;
   
      div {
        height: 30px;
        line-height: 30px;
        margin-bottom: -5px;
        cursor: pointer;
        width: 33%;
        float: left;
      }
   
      span {
        display: inline-block;
        vertical-align: -0.15em;
        fill: currentColor;
        overflow: hidden;
      }
    }
  }
  </style>
Home.vue中使用IconSelect
<template>
    home
    <!-- <svg-icon icon-class="tree" size="40px"/>
    <svg-icon icon-class="tree2" size="50px"/> -->

    <div style="width:300px">
        <icon-select @selected="selected"></icon-select>
    </div>
</template>

<script setup>
import IconSelect from '@/components/IconSelect/index.vue'
import { reactive, ref } from "vue";

const state = reactive({
    icon: '',
})

function selected(name) {
    console.log(state.icon)
    state.icon = name;
}

</script>

<style lang="scss"></style>

在这里插入图片描述

vue2自定义svg图标组件

1. 安装svg-spriteloader

npm install svg-sprite-loader -D

2. 创建图标所在文件夹

项目 src 目录新建 src/icons/svg 目录存放 svg 图标文件)。
在这里插入图片描述

3. 配置vue.config.js

const { defineConfig } = require('@vue/cli-service')

const path = require('path')
const resolve = dir => path.join(__dirname, dir)

module.exports = defineConfig({
  transpileDependencies: true,
  chainWebpack(config) {
    // 配置 svg-sprite-loader
    config.module
      .rule('svg')
      .exclude.add(resolve('src/icons'))
      .end()
    config.module
      .rule('icons')
      .test(/.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()
  }
})

4. SvgIcon.vue图标组件封装

在src/components下创建SvgIcon.vue
或者:在src/components下创建SvgIcon文件夹,在里边创建index.vue)

<template>
  <svg className="svg-icon" aria-hidden="true">
    <use :xlink:href="iconName"/>
  </svg>
</template>
<style>
.svg-icon {
  width: 1.5em;
  height: 1.5em;
}
</style>
<script>
export default {
  props: {
    iconClass: {
      type: String,
      required: true
    }
  },
  computed: {
    iconName () {
      return `#icon-${this.iconClass}`
    }
  }
}
</script>

5.创建svg文件的入口文件icon.js

src/icons 下创建 icons 目录的入口文件 index.js ,负责svg文件加载

import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'
Vue.component('svg-icon', SvgIcon)
 
/**
 * require.context参数说明
 * './svg' 代表查找文件路径
 * false 代表是否查找目录
 * /.svg$/ 代表匹配文件正则
 *
 */
const svg = require.context('./svg', false, /.svg$/)
const requireAll = (requireContext) => requireContext.keys().map(requireContext)
requireAll(svg)

6.main.js中引入icon.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

import '@/icons'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

7. Home.vue中使用SvgIcon组件

<template>
    <div>
        Home
        <svg-icon icon-class="tree"></svg-icon>
        <svg-icon icon-class="tree2"></svg-icon>
    </div>
</template>

<script>

export default {
    name: 'Home',
    components: {
    }
}
</script>

<style>

</style>

在这里插入图片描述

原文地址:https://blog.csdn.net/qq_16992475/article/details/129695582

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_48866.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注