svg图标使用(use标签为0、导航栏上使用svg图标跟随状态变色)

svg图标使用

介绍:本文主要介绍svg图标的使用方法,分别介绍在vue脚手架和vite中如何使用,以及遇到的问题:use标签为0导致svg不显示、如何在导航栏使用svg图标以及跟随状态(选中、悬浮)svg图标变色。

1.svg图标的使用-vue脚手架

一开始先来介绍vue脚手架中使用svg的方法

js 复制代码
// 首先要安装包
npm install svg-sprite-loader -D

components/SvgIcon/index.vue

  • aria-hidden会让浏览器阅读内容的时候略过这个,避免残障人士发生歧义。
js 复制代码
<template>  
    <div class="icon-wrapper">  
        <svg class="icon" aria-hidden="true">  
            <use :xlink:href="iconName"></use>  
        </svg>  
    </div>  
</template>  
  
<script setup>  
import {computed} from "vue";  
  
const props = defineProps({  
    name: {  
        type: String,  
        default: ''  
    }  
})  
  
let iconName = computed(()=> {  
    return `#icon-${props.name}`  
})  
  
</script>  
  
<style lang="less" scoped>  
.icon-wrapper {  
    display: inline-block;  
}  
.icon {  
    width: 100%;  
    height: 100%;  
    // 继承当前元素color的颜色,如果当前元素的color未设定,则继承祖先元素的color值。
    fill: currentColor;
}  
</style>

vue.config.js

js 复制代码
const { defineConfig } = require('@vue/cli-service')
const path = require('path');

function resolve(dir) {
  return path.join(__dirname, dir)
}
module.exports = defineConfig({
  transpileDependencies: true,
    configureWebpack:{
        resolve: {
            //配置简写路径
            alias: {
                '@': resolve('src'),
                'assets': resolve('src/assets')
            }
        },

    },
    chainWebpack: config => {
        const svgRule = config.module.rule('svg');
        // 清空默认svg规则
        svgRule.uses.clear();
        //针对svg文件添加svg-sprite-loader规则
        svgRule
            .test( /.svg$/)
            .use('svg-sprite-loader')
            .loader('svg-sprite-loader')
            .options({
                symbolId: 'icon-[name]'
            });
    }
})

src/icons/index.js

  • requireContext.keys().map(requireContext)主要用于批量导入时的作用
  • require.context是webpack内置的方法,第一个参数:路径,第二个参数:是否检索子文件夹,第三个参数:文件的正则表达式,一般是文件名
js 复制代码
const requireAll = requireContext => {
    console.log('requireContext.keys().map(requireContext)',requireContext.keys().map(requireContext))
    return requireContext.keys().map(requireContext)
}
// 这里要写上你svg图标的路径
const req = require.context('@/icons/svg', true, /.svg$/)

requireAll(req)

scr/plugins/svgImport.js

  • 这里进行组件的注册
js 复制代码
import '@/icons/index'
import SvgIcon from "@/components/SvgIcon.vue";

export default {
  install: (app) => {
    app.component('svg-icon', SvgIcon)
  }
}

main.js

js 复制代码
import { createApp } from 'vue'  
import App from './App.vue'  
import router from './router'  
import svgImport from '@/plugins/svgImport'  
  
createApp(App)  
    .use(router)  
    .use(svgImport)  
    .mount('#app')

页面中使用:

js 复制代码
<svg-icon name="select-all-active" class="icon1"></svg-icon>

文件夹:

问题出现:

当到这里的时候,我们就会发现svg没有显示,使用开发者工具去查看,就发现svg里面的use标签宽高是0,那么为什么会这样呢?这时候我们打开控制台看看输出了什么: 这里是一个数组,数组里面是一个字符串,当你遇到这种情况的时候,那么use标签宽高很可能就是0*0.

正确的打印 这里的打印我们可以看到,也是一个数组,但是数组里面是一个对象,里面其实是我们svg图标的内容,如果没有读取到这些内容,就导致我们的use标签宽高是0*0

解决问题 把vue.config.js修改一下

js 复制代码
const { defineConfig } = require('@vue/cli-service')
const path = require('path');

function resolve(dir) {
  return path.join(__dirname, dir)
}
module.exports = defineConfig({
  transpileDependencies: true,
    configureWebpack:{
        resolve: {
            //配置简写路径
            alias: {
                '@': resolve('src'),
                'assets': resolve('src/assets')
            }
        },
    },
    chainWebpack: config => {
        config.module
            .rule('svg')
            .exclude.add(resolve('src/icons'))//svg的存储地址
            .end()
        config.module
            .rule('icons')
            .test(/.svg$/)
            .include.add(resolve('src/icons'))//svg的存储地址
            .end()
            .use('svg-sprite-loader')
            .loader('svg-sprite-loader')
            .options({
                symbolId: 'icon-[name]'
            })
            .end()
    }
})

效果

2.svg图标的使用-vite

js 复制代码
npm i vite-plugin-svg-icons -D

vite.config.js

js 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";


export default defineConfig({
  plugins: [
      createSvgIconsPlugin({
          // 指定需要缓存的图标文件夹
          iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')],
          // 指定symbolId格式
          symbolId: "icon-[dir]-[name]"
      }),
      vue(),

  ],

  resolve: {
    // 设置路径别名
    alias: {
      '@': path.resolve(  __dirname, './src'),
      '*': path.resolve('')
    },
  }
})

components/SvgIcon/index.vue

js 复制代码
<template>  
    <svg :class="svgClassName">  
        <use :xlink:href="useIconName"></use>  
    </svg>  
</template>  
  
<script setup>  
import { computed, defineProps } from 'vue'  
const props = defineProps({  
    name: {  
        type: String,  
        required: true  
    },  
})  
const useIconName = computed(() => `#icon-${ props.name }`)  
const svgClassName = computed(() => {  
    if(props.name) {  
        return `svg-use-icon icon-${ props.name }`  
    }  
    return 'svg-use-icon'  
    })  
</script>  
  
<style scoped>  
.svg-use-icon {  
    width: 100px;  
    height: 100px;  
    fill:currentColor;  
}  
</style>

main.js

js 复制代码
import 'virtual:svg-icons-register';
import SvgIcon from "@/components/SvgIcon/index.vue";
const app = createApp(App);
// 全局注册
app.component('svg-icon', SvgIcon)

app.mount('#app')

使用:

js 复制代码
<svg-icon name="select-all-active"></svg-icon>

可能遇到的报错

解决:

js 复制代码
 npm install fast-glob -D

3.导航栏上使用svg图标跟随状态变色

关键代码:

  • 一定要给svg标签绑定上fill:currentColor

  • 把每一个svg图标的fill属性改为inherit

  • 一个svg图标里面会有多个fill属性,一定要全部改为inherit

效果

  1. 选中时候和未选中时候
  2. 鼠标悬浮状态

总结:

  1. 本文主要介绍svg图标如何在vue脚手架和vite中使用
  2. 解决use标签渲染宽高为0*0的问题
  3. 如何在导航栏上使用svg标签跟随状态变色,状态:未选中、选中、悬浮
  4. 有什么问题可以下方留言或者私信哦。
相关推荐
前端的日常12 分钟前
以下代码,那一部分运行快
前端
GeGarron13 分钟前
Drawing:专注高效画图,让每一次创作都值得被珍藏
前端
梨子同志13 分钟前
Vue v-model 指令详解
前端·vue.js
杨进军13 分钟前
简易实现 React 页面初次渲染
前端·react.js·前端框架
血舞之境15 分钟前
同名类引发问题:没见过世面导致遇见各种诡异的问题
前端
杨进军16 分钟前
实现 React 多个原生标签子节点渲染
前端·react.js·前端框架
前端的日常16 分钟前
AI 工具中,经常提到的 mcp 是什么,有哪些与前端方向结合的场景?
前端
嘉小华16 分钟前
Android 协程全景式深度解析:第四章 Flow响应式流
android·前端
Tina_晴18 分钟前
【基础篇】Promise初体验+案例分析(上)
前端·javascript·面试
断竿散人20 分钟前
浏览器 History 对象完全指南:从 API 原理到 SPA 路由实战
前端·javascript·vue-router