Vue 加载 svg icon

我们都知道SVG替代图片作为图标的好处,但如何能够方便的加载在VUE工程中呢;通过直接插入SVG代码方式画,当然是OK的,但这种方式是不是很LOW,一个两个还好,如果icon太多了,那就不好管理了;

咋样才能更加友好便捷使用呢,这两天研究 2 种方式,原理都是提前加载 svg 模板到 body 中,然后在需要用到的 svg icon 的地方,用 use 标记去实例化对应的 svg ;见:http://know.webhek.com/svg/svg-symbol.html

使用icon font等CDN方式在线加载:

好处是不用下载到本地,不用管理svg文件,方便那是真的

坏处就是如果我们需要 icon fillColor 根据 currentColor 更改而更改的话,就不好使了,因为通常来将,加载的 svg 都是有 fillColor 的,此时在引用的地方,使用 fill color 是无效的,如下图;所以可能需要准备多套资源,增加工作量,且资源多了也会对内存和加载速度有影响;当然也可以准备不带 fill 的资源,iconfont 官网说明里给了一个不带fill的链接,我自己反正是不知道怎么弄到 iconfont 上去;

image

使用svg-sprite-loader等插件本地加载

好处当然是可以定制啦,多色也没问题,只是可能需要打开文件,去掉部分 fill 属性;这样在外面传入的 fill 才能生效;

坏处当然是要本地维护这些资源了,而且需要搞定一些配置,才能快乐使用,这配置是真的没那么简单,这个后面我会讲到;


下面我就讲讲如何使用吧

1、使用 iconfont 等 CDN 链接方式加载模板;

前面说了,这个是真的简单方便

首先,默认在 iconfont 上的账户有资源啦;选择 Symbol,复制链接加到你的项目中;

image
image

项目 run 起来后,在 body 中可以看到加载好的模板;

image

然后在需要使用的地方,插入代码

<svg class="icon"><use xlink:href="#iconzu91-copy"></use></svg>

代码中#iconzu91-copy为模板中对应的 symbol id 值;加载的效果如下:

image

是不是超简单;

2、使用 svg-sprite-loader 等插件方式加载;

  • 首先当然是安装插件了,npm install svg-sprite-loader -D

  • 第 2 步,下载svg 放到工程目录下,我是放在这里的,大家随意,开心就好;

image
  • 第 3 步,批量引用 svg 文件;

    在 svgicons 下新建一个 index.js,加入如下代码

const context = require.context(".", false, /\.svg$/);
const requireAll = (requireContext) => {
  return requireContext.keys().map(requireContext);
};
requireAll(context);

webpack 关于 require.context 的解释,可以看一下;
我就不解释了,水平有限,还是看官方文档吧;

  • 第 4 步,配置 webpack 下模块加载配置,配置的目的是要让 svg-sprite-loader 将对应的 svg 文件的模板编译加载到body中

配置要分两种情况,看工程是用 vue cli 2 还是 3 及以上创建的了;

cli2 的配置如下(cli3 的可以直接跳到 **cli3配置 **)

需要在 webpack.base.conf.js 中的 module 下的 rules 下添加如下配置

{
        test: /\.svg$/,
        loader: "svg-sprite-loader",
        include: [resolve("src/assets/svgicons")],
        options: {
          symbolId: "svg-[name]"
        }
}

这个意思是说,我们用 svg-sprite-loader 这个插件去加载 src/assets/svgicons 文件夹下所有的以 .svg 结尾的文件,并且模板中 symbol id 是以 svg- 开头,文件名称结尾;当然,这个前缀要不要都行;

注意,rules 中,可能还有其他的 loader 会去处理 svg 的,我们可以在对应的插件 loader 下配置exclude: [resolve("src/assets/svgicons")],如我这里需要配置,这样 url-loader 就不会去处理编译对应文件加下的文件了;

{
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: "url-loader",
        exclude: [resolve("src/assets/svgicons")],
        options: {
          limit: 10000,
          name: utils.assetsPath("img/[name].[hash:7].[ext]")
        }
}

完了后,就可以run 起来,然后就可以看到 body 中已加载好了模板;


body 中 svg 模板.PNG
cli3及以上的配置如下(cli2 的可以跳过这一步)

首先在根目录新建 vue.config.js 文件,

这个地方解释一下,配置同 cli2,只不过这里看起来是没有在 cli2 中显得那么直观;

下面拆解下我自己是如何配置这部分的
首先到 node_modules/@vue/cli-service/lib/config/base.js 下查看默认配置

webpack base rules.PNG

可以看到,默认处理 svg 文件的是 file-loader,这里我们把默认的svg的配置里加一个 exclude,同 cli2 中配置,这样 file-loader 和 我们将要设置的 svg-loader 就不会重复处理我们的src/assets/svgicons 下的 svg 文件;当然,我们也可以覆盖svg rule,这样所有的 svg 文件就会采用我们覆盖的 loader 去处理 svg 文件;

新建一个规则配置

/* eslint-disable */
const path = require("path");// @ts-ignore
/* eslint-enable */

function resolve(dir) {
  // 路径可能与你的项目不同
  return path.join(__dirname, dir);
}

module.exports = {
  chainWebpack: (config) => {
    // exclude 配置默认的 svg 规则下不处理对应我定义的文件夹下的 svg 文件
    config.module.rule("svg").exclude.add(resolve("src/assets/svgicons")).end();
    // 新建一个 svgIcon rule,配置它的加载方式
    config.module
      .rule("svgIcon")
      .test(/\.svg$/)
      .use("svg-sprite")
      .loader("svg-sprite-loader")
      .options({
        symbolId: "svg-[name]",
      })
      .end()
      .include.add(resolve("src/assets/svgicons"))
      .end();
  },
};

覆盖配置如下

module.exports = {
  chainWebpack: (config) => {
    // 先清除 uses,否则 svg 文件就会先被默认的 fileloader 处理一次,然后再被 svg-sqrite-loader 再处理一次
    config.module.rule("svg").uses.clear();
    config.module
      .rule("svg")
      .test(/\.svg$/)
      .use("svg-sprite")
      .loader("svg-sprite-loader")
      .options({
        symbolId: "svg-[name]",
      })
      .end()
      .include.add(resolve("src/assets/svgicons"))
      .end();
  },
};

完了后,就可以run 起来,然后就可以看到 body 中已加载好了模板;


body 中 svg 模板.PNG
  • 第 5 步,看疗效:

在需要使用 svg icon 的地方加入如下代码

<svg class="svg-icon"> <use :xlink:href="svg-svg-on-dark" /> </svg>
<svg class="svg-icon"> <use :xlink:href="svg-eye" /> </svg>

成功加载


image

后面我会再研究下 vue-svg-loader 加载 svg icon

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容

  • 第一种:直接使用SVG文件地址 1.创建组件 /components/Svg.vue 2.全局注册组建 /main...
    EJYeh阅读 3,335评论 2 0
  • 之前说过icon-fonts解决方案可以一次性加载纯色图标,并且相对于精灵图更小更灵活;那渐变色或者组合颜色的图标...
    我是你班主任阅读 14,196评论 0 5
  • 目录 iconfont的三种使用方式及其优缺点 封装svg组件 svg雪碧图 自动导入svg图标 封装svg组件 ...
    胡儒清阅读 15,336评论 0 8
  • 前言 网页图标展示方式大概可以分为以下几类 img 标签。最原始的方式,不支持改变颜色 css sprites。其...
    雨翼195阅读 1,863评论 0 1
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,536评论 28 53