你遇到过最难的技术问题?

630 阅读3分钟

一、引入svg的简单方法 在iconfont上选好图标,然后生成一个svg.js, 把这个svg.js保存到项目里,然后引用,就可以使用svg了代码示例: Icon.vue

复制代码 上面这种方法虽然简单,但是又有点麻烦,因为当我们需要更新svg图标,就需要重新登录iconfont网站,获取新的svg.js, 然后下载下来,再引入项目,能不能让更新svg简单一些?答案是可以的。所以我们的目标是:通过webpack来引入svg, 如果有新的svg, 直接把下载好的svg复制到对应的icon文件夹, 然后在任何一个组件里写就可以用这个svg.接下来将一步步实现这个目标

二、如何用Vue@cli引入svg?

2.1 安装svg loader 我们可以很快地搜索到需要安装svg-sprite-loader, 才能在webpack里使用但问题是,安装过后,需要配置,但官方文档里的配置是写在webpack.config.js, 而我们的项目是用Vue@cli搭建的,并没有webpack.config.js这个文件,只有vue.config.js

2.2 配置vue.config.js 所以我们需要做的就是把官方文档里 webpack.config.js 关于svg-sprite-loader 的配置 翻译成 vue.config.js 里的配置。于是我就去读了vue的官方文档,发现可以在vue.config.js里用一个chainWebpack来修改webpack的配置Vue官方给的例子是: // vue.config.js module.exports = { chainWebpack: config => { config.module .rule('vue') .use('vue-loader') .loader('vue-loader') .tap(options => { // 修改它的选项... return options }) } } 复制代码 于是照猫画虎,配置写出来我们需要的vue.config.js 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() //不需要解析成文件
config.plugin('svg-sprite').use(require('svg-sprite-loader/plugin'), [{plainSprite: true}])
config.module.rule('svg').exclude.add(dir) // 其他svg loader排除icons目录

}

}

复制代码 这样配置完成之后,我们就可以在项目里引用svg了

复制代码

2.3 给svg去色 写芒果记账时,有一个需求是高亮svg图标,即本身灰色的svg图标高亮成黄色或者红色,但在写CSS时,我发现有些svg自己带了颜色,无法修改,怎么办呢?我去打开svg文件,读了读里面的内容,发现一个属性叫fill, 表示填色。于是进一步在控制台里做实验,发现如果去掉svg里的fill属性,那么这个svg就没有自带颜色了。但问题是,这么多svg图标,难道我们要一个一个地去删除fill属性?当然不可能。通过搜索,我发现了一个Loader叫 'svgo-loader', 它可以去除fill标签, 配置如下 config.module .use('svgo-loader').loader('svgo-loader') // .tap(options => ({...options, plugins: [{removeAttrs: {attrs: 'fill'}}]})).end() 复制代码 于是现在我们的vue.config.js是: 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目录

} } 复制代码 这样就可以顺利引入svg且给svg去色

2.4 抽取Icon组件 如果每次引用svg都要写一次:

复制代码 实在是有些麻烦,于是我们可以抽取出一个Icon组件,每次这样就好。 Icon组件的实现很简单,就是把本身的代码包裹一层,然后接收一个Name作为参数 Icon组件:

复制代码

2.5 一次性引入所有svg文件 目前还存在的问题是我们是一个一个地引入svg图标,能不能一次性引入一整个svg文件夹?可以!用一个ImportAll 方法即可 const importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext); try { importAll(require.context('../assets/icons', true, /.svg$/)); } catch (error) { console.log(error); } 复制代码 现在我们解决了全部的问题,如果有新的svg, 就把它复制到assets/icons目录下,然后在项目里直接就可以愉快地用它了!

作者:510酱 链接:juejin.cn/post/688564… 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

SVG问题一: SVG给了颜色,不变色 SVG自带的属性,里面有 fill de 一个属性

SVG问题二: 在做记账项目的时候,我需要用到很多的SVG,但是每个引入都得写的很复杂,我给他封装过后,四月了svg-sprite-loader来引入所有的icon,把icon变成一个SVG,所有的icon在SVG中作为一个symbol,然后我就发现一个BUG,这个BUG就是webstorm永远都无法去 import 一个SCSS,当时就找原因找解决办法,后来才知道,因为WebStorm在遇到这个loader的时候,发现这个loader的实现有问题,webstorm和这个loader冲突了,webstorm无法解析这个loader,那这个webpack的配置我不是解析不了了?

我发现他们之间的这个关联大改用了一下午,于是我就去看这个SVG-loader的GitHub的依属列表,然后就发现里面有人说这个问题,有没有人解决呢,于是我就看了- GitHUb的代码贡献,然后就发现 也有人在贡献代码,但是迟迟没有合并到loader的源代码里面呢,也不知道,于是我就只能自己解决这个问题,于是我把他的源代码fork了一份,然后把别人提的Pr给merge到我下载的源代码里面,那这样的话,我的这个版本就可以用了,于是我又使用npm publish 把我的版本发布到npm上去,然后自己再去下载自己改的那个版本,终于解决了这个问题