Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Vue | 使用 SVG sprite loader 来引入 svg

Vue | 使用 SVG sprite loader 来引入 svg

作者头像
Zkeq
发布于 2022-09-20 07:47:12
发布于 2022-09-20 07:47:12
3.3K00
代码可运行
举报
文章被收录于专栏:ZkeqZkeq
运行总次数:0
代码可运行
首先安装
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
yarn add svg-sprite-loader -D

webpack.config.js 翻译成 Vue.config.js

这个库给的示例代码是 webpack.config.js 但是我们现在在用的是 Vue

官方的代码是这样的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// webpack >= 2
{
  test: /\.svg$/,
  loader: 'svg-sprite-loader',
  options: { ... }
}
// webpack >= 2 multiple loaders
{
  test: /\.svg$/,
  use: [
    { loader: 'svg-sprite-loader', options: { ... } },
    'svg-transform-loader',
    'svgo-loader'
  ]
}

翻译成 Vue.config.js,用到的 chainWebpack

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const path = require('path')
module.exports = {
  lintOnSave: false,
  chainWebpack: config =>{
    const dir = path.resolve(__dirname, 'src/assets/icons')
    config.module
      .rule('svg-sprite')
      .test(/\.svg$/)
      .include.add(dir).end() // 包含 icons 目录
      .use('svg-sprite-loader').loader('svg-sprite-loader').options({extract:false}).end()
      // 下文会解决一个 svg 填充问题,也就是下面被注释掉的代码
    config.plugin('svg-sprite').use(require('svg-sprite-loader/plugin'), [{plainSprite: true}])
    config.module.rule('svg').exclude.add(dir) // 其他 svg loader 排除 icons 目录
    // config.module
    //   .rule('svg-sprite')
    //   .test(/\.(svg)(\?.*)?$/)
    //   .include.add(dir).end()
    //   .use('svg-sprite-loader-mod').loader('svg-sprite-loader-mod').options({extract: false}).end()
    //   .use('svgo-loader').loader('svgo-loader')
    //   .tap(options => ({...options, plugins: [{removeAttrs: {attrs: 'fill'}}]}))
    //   .end()
    // config.plugin('svg-sprite').use(require('svg-sprite-loader-mod/plugin'), [{plainSprite: true}])
    // config.module.rule('svg').exclude.add(dir)
  }
}

其他备注

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// svg 相关组件版本
     "svg-sprite-loader": "^6.0.11",
     "svgo-loader": "^2.2.1"

shims-vue.d.ts 中添加

这一步是为了解决 ts 报错

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

declare module '*.svg' {
  const content: string;
  export default content;
}

接着在 TS 里面引入
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script lang="ts">
// 笑死我了,这是菜鸡写法
    import x from '@/assets/icons/Labels.svg'
    import y from '@/assets/icons/Money.svg'
    console.log(x)
    console.log(y)
</script>

这一步的作用就是在 htmlhead 部分嵌入一个 symbol ,接着我们在 template 里面用 <use /> 标签就可以使用啦

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
    <div class="nav">
      <router-link to="/money">
        <svg>
            <use xlink:href="#Money" />
        </svg>
      </router-link>
    </div>
</template>

想必看出来了,这样引入真的 很麻烦,如果我们有几十个 svg ,难道要一个一个的引入??

而且每次都要写 <svg><use /></svg> 好麻烦,我们可不可以把它封装成一个组件呢?

引入整个 svg 目录?
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 let importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
  // 这玩意是搜的全网搜到的?
  try {importAll(require.context('../assets/icons', true, /\.svg$/));} catch (error) {console.log(error);}
  // 如果不加 try,在单元测试的时候可能会遇到问题
  
  // 牛逼,好用

icon 封装成组件

@/components/Icon.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
    <svg class="icon">
        <use :xlink:href="'#' + name" />
    </svg>
</template>
<script lang="ts">
    let importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
    // 这玩意是搜的全网搜到的?
    try {importAll(require.context('../assets/icons', true, /\.svg$/));} catch (error) {console.log(error);}
    // 如果不加 try,在单元测试的时候可能会遇到问题
    export default {
        name: 'Icon',
        props: ['name']
        // 以下代码是自动生成的
        // props: {
        //     name: {
        //         type: String,
        //         required: true
        //     }
        // }
        
    }
</script>
<style lang="scss" scoped>
// 这个样式代码是阿里矢量字体库里面给的css
    .icon {
        width: 1em;
        height: 1em;
        vertical-align: -0.15em;
        fill: currentColor;
        overflow: hidden;
    }
</style>

@/main.ts 全局注册

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import Icon from "@/components/Icon.vue";
Vue.component("Icon", Icon)

然后直接在 view 里面使用 <Icon />即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
    <div class="nav">
      <router-link to="/money">
        <Icon name="Money"/>
      </router-link>
      |
      <router-link to="/lables">
        <Icon name="Labels"/>
      </router-link>
      |
      <router-link to="/statistics">
        <Icon name="Statistics"/>
      </router-link>
    </div>
</template>

遇到的一个小 bug: fill 颜色

尝试实现切换标签页的时候自动更改填充颜色来达到突出显示的效果

但是并不是所有的 svg 都会自动变色, 只有一些标签会起作用… 于是我直接干脆调成了这样

和这样

笑死我了,直接逃避这个问题

经过排查发现是 svg 代码里面的 fill 属性来控制了颜色,从而 css 不能从外部更改颜色

如图:

手动删掉此属性即可正常用css指定颜色,但是如果有很多svg.这样的话未必太过麻烦

我们可以使用一个叫做 svgo-loader 的插件来解决此问题

不知道是什么原因,高版本的这个插件会导致加载不出 svg 的 bug,我使用的是以下版本,是正常使用的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 和上文提到的一样
{
    "devDependencies": {
        "svg-sprite-loader": "^6.0.11", 
        //已知 svg-sprite-loader 的 4.1.6 版本会有 bug
        // 故推荐使用高版本的,最新版已经修复了 bug,推荐使用 ^6.0.11
        "svgo-loader": "^2.2.1", // 即此版本可正常使用
    }
}

我的完整的版本号(可以正常使用的,就第一个 loader 版本号比以上高一些)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "name": "morney-3",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "3.15.2",
    "register-service-worker": "1.7.2",
    "vue": "2.6.14",
    "vue-class-component": "7.2.6",
    "vue-property-decorator": "9.1.2",
    "vue-router": "3.5.2",
    "vuex": "3.6.2"
  },
  "devDependencies": {
    "@types/jest": "24.0.25",
    "@typescript-eslint/eslint-plugin": "4.28.4",
    "@typescript-eslint/parser": "4.28.4",
    "@vue/cli-plugin-babel": "4.5.13",
    "@vue/cli-plugin-eslint": "4.5.13",
    "@vue/cli-plugin-pwa": "4.5.13",
    "@vue/cli-plugin-router": "4.5.13",
    "@vue/cli-plugin-typescript": "4.5.13",
    "@vue/cli-plugin-unit-jest": "4.5.13",
    "@vue/cli-plugin-vuex": "4.5.13",
    "@vue/cli-service": "4.5.13",
    "@vue/eslint-config-typescript": "7.0.0",
    "@vue/test-utils": "1.2.2",
    "eslint": "6.8.0",
    "eslint-plugin-vue": "6.2.2",
    "sass": "1.36.0",
    "sass-loader": "8.0.2",
    "svg-sprite-loader": "^6.0.11",
    "svgo-loader": "^2.2.1",
    "typescript": "4.1.6",
    "vue-template-compiler": "2.6.14"
  }
}

安装完之后,我们需要配置 vue.config.js 文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+      .use('svgo-loader').loader('svgo-loader')
+      .tap(options => ({...options, plugins: [{removeAttrs: {attrs: 'fill'}}]}))
+      .end()

完整的 vue.config.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module.exports = {
  lintOnSave: false
}
const path = require('path')
module.exports = {
  lintOnSave: false,
  chainWebpack: config =>{
    const dir = path.resolve(__dirname, 'src/assets/icons')
    config.module
      .rule('svg-sprite')
      .test(/\.svg$/)
      .include.add(dir).end() // 包含 icons 目录
      .use('svg-sprite-loader').loader('svg-sprite-loader').options({extract:false}).end()
      .use('svgo-loader').loader('svgo-loader')
      .tap(options => ({...options, plugins: [{removeAttrs: {attrs: 'fill'}}]}))
      .end()
    config.plugin('svg-sprite').use(require('svg-sprite-loader/plugin'), [{plainSprite: true}])
    config.module.rule('svg').exclude.add(dir) // 其他 svg loader 排除 icons 目录
  }
}

收工,效果如下

PS: vue.config.jseslint 错误怎么办?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

/* eslint-disable */ 

把这句话添加到 vue.config.js 的第一行即可

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
52·[Vue项目]旺财记账-导航栏
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
DriverZeng
2022/11/08
1.4K0
52·[Vue项目]旺财记账-导航栏
前端项目搭建实战(Vue)
同时我们需要对路由做一定的控制,比如未登录时只允许访问登录页,以及对页面跳转做一些样式上的优化。
逃跑计划
2022/08/03
1.8K4
前端项目搭建实战(Vue)
从龟速 11s 到闪电 1s,详解前端性能优化之首屏加载
全文共6511字/词,阅读大概需要13分钟,太长不看党请直接移步👉「开始优化」部分直接查看优化手段 背景 前段时间公司服务器网络波动,网站访问变慢,一些性能问题也随之暴露了出来。纷纷反馈在这样的弱网条件下,访问新项目时,加载了近1分钟都没加载出来,而访问其他页面顶多也就30-40s。 在网络恢复后,尝试访问了下页面,无缓存首次打开需要等待近11s的时间,最大的资源达到了3.7M... 在对项目做了一些优化处理后,再次无缓存打开可以发现网页几乎是秒开,平均耗时在1s以内 在这里总结记录一下,基本上都是一些
@超人
2021/12/17
3.3K0
从龟速 11s 到闪电 1s,详解前端性能优化之首屏加载
如何在VUE项目中引入SVG图标
SVG(即“可缩放矢量图形”)图标在诸多场合下,往往胜过一般的位图标记(例如PNG、JPG、GIF等)。
HelloWorldZ
2024/03/20
1.1K0
如何在VUE项目中引入SVG图标
Vue 项目引入 SVG 图标
SVG 是一种可缩放矢量图形(Scalable Vector Graphics,SVG)是基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式。SVG 由 W3C 制定,是一个开放标准。
数媒派
2022/12/01
2.2K0
BuildAdmin04:vue加载本地svg图标
上篇文章主要讲了图标组件Icon的实现,主要包括了两种常用的图标。今天就讲一下如何在Icon中加载本地的svg图标。
叫我阿柒啊
2024/01/17
4830
BuildAdmin04:vue加载本地svg图标
Vue3 使用 svg-sprite-loader 实现 svg 图标按需加载
前面文章有讲到 svg 图标按需加载的优势以及 Vue 如何使用 vue-svg-icon 实现 svg 图标按需载入 今天来学习一下使用 svg-sprite-loader 在 Vue3 项目中实现图标按需加载
Leophen
2020/12/22
7.6K1
使用svg-sprite-loader 遇到的问题
现有的项目是从另一个项目移植过来的, 并不是完全移植 为了减小项目的体积 前端组长将一些暂时用不到的组件 node包都剔除了 这也就引出了一下的问题
拿我格子衫来
2022/01/23
1.6K0
基于Vue的前端架构,我做了这15点
为什么选择了两个?因为公司团队跟倾向于使用 scss 开发,less 是为了覆盖 ant design vue 的样式,stylus 只有我自己喜欢这种风格。
落落落洛克
2021/01/08
2.7K0
基于Vue的前端架构,我做了这15点
svg渲染use占位符宽高都是0,页面显示空白问题
经过分析是少了个解析插件 svg-sprite-loader ,用npm安装一下,然后需要在vue.config.js中添加配置
李维亮
2022/12/07
1.9K0
svg渲染use占位符宽高都是0,页面显示空白问题
搞个一手环境-处理svg组件(2)
svg-sprite-loader 可以多个svg图标合并. 使用时只需根据合并的symbol的id即可.
刘嘿哈
2022/10/25
3010
vue菜鸡实践
根目录创建vue.config.js文件 基本配置,configureWebpack属性,值是对象时的配置
刘嘿哈
2022/10/25
3490
vue菜鸡实践
在 Vue 项目中更优雅的使用 icon
在 Web 开发中,我们经常会用到 icon,icon 的使用经历了从图片到字体,再到 svg 的演变过程,也产生出相应的 icon 库,如雪碧图、Font Awesome、Iconfont 等等。
Cell
2023/09/15
5710
如何在Vue项目中更优雅地使用svg
最近看项目视频的时候对里面使用 svg 的方式感到很好奇,于是去网上查了一下,发现 svg 竟然也有类似于 css 雪碧图一样的用法,也就是 svg-sprite(孤陋寡闻了),而且配合插件后能够以组件化的方式使用 svg,非常方便。这里记录下一些相关用法。
Chor
2020/05/06
13.3K1
React 造轮子系列:Icon 组件思路
本轮子是通过 React + TypeScript + Webpack 搭建的,至于环境的搭建这边就不在细说了,自己动手谷歌吧。当然可以参考我的源码。
前端小智@大迁世界
2019/06/15
4.8K1
T系列部署教程3:前端项目的部署运行
接着请同学们打开 package.json 文件,删除 eslintConfig 和 browserslist 字段,删除所有 eslint 、node-sass、sass-loader的依赖,如下图所示。
Designer 小郑
2024/05/26
2480
T系列部署教程3:前端项目的部署运行
vue.config.js打包优化(有效)「建议收藏」
//百度上的资料五花八门让人眼花缭乱,别急,这时候我替你亲身经历了,有需要的可以参考下,先上效果图,以免你们以为我吹牛逼,嘻嘻
全栈程序员站长
2022/07/01
1.8K0
vue.config.js打包优化(有效)「建议收藏」
chainWebpack长用配置集合
chainWebpack长用配置方式 //vue.config.js module.exports={ chainWebpack:config=>{ } } 1 输入输出配置 module.exports = { chainWebpack: config => { // 清理所有默认入口配置 config.entryPoints.clear(); // 增加一个入口main config.entry("main").add("./src/main.js");
刘嘿哈
2022/10/25
1.6K0
SVG 图标在React项目中的优化
官方文档:https://webpack.docschina.org/loaders/url-loader/
javascript.shop
2019/09/04
3.7K0
SVG 图标在React项目中的优化
Vue项目初次访问慢的一种解决思路
将打包后的dist文件夹上传到服务器上部署(nginx、tomcat都可以,我的环境是nginx),访问:
行百里er
2022/03/30
1.9K0
Vue项目初次访问慢的一种解决思路
相关推荐
52·[Vue项目]旺财记账-导航栏
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验