# Icon 组件
本项目使用vue-cli作为脚手架开发.包含了我所需要的配置: 使用 Vue + Vuex + Vue-router 作为视图层的开发.使用 TypeScript 代替 JavaScript.使用 SCSS 代替 CSS. 但是还有一些配置需要自己完成.
# SVG loader 的配置
由于使用了 TypeScript, 我们需要在声明文件(shims-vue.d.ts
)里去声明一下 svg:
declare module "*.svg" { const content: string; export default content; }
Copied!
1
2
3
4
2
3
4
这样在引入 svg 时不会报错了.
接下来引入 svg 需要的 loaders: yarn add svg-sprite-loader svgo-loader
. 然后在vue.config.js
里配置:
const path = require("path"); module.exports = { chainWebpack: config => { const dir = path.resolve(__dirname, "src/assets/icons"); // 存放icons的目录 config.module .rule("svg-sprite") .test(/\.svg$/) .include.add(dir) .end() // 包含 icons 目录 .use("svg-sprite-loader") //使用此loader .loader("svg-sprite-loader") .options({ extract: false }) .end() .use("svgo-loader") .loader("svgo-loader") .tap(options => ({ ...options, plugins: [{ removeAttrs: { attrs: "fill" } }] // 删除svg的fill属性 })) .end(); config .plugin("svg-sprite") .use(require("svg-sprite-loader/plugin"), [{ plainSprite: true }]); config.module.rule("svg").exclude.add(dir); // 其他 svg loader 不会解析 icons 目录 } };
Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
svg-sprite-loader
的作用是解析 svg 文件, 但要注意, 如果使用 WebStorm 时, 且svg-sprite-loader
的版本低于4.2.0
时, 引入全局 SCSS 文件会报错(是 WebStorm code assistance analyzer 的错, 它没能解析出来). 不过在4.2.0
及以上的版本中这个 bug 已被修复
svgo-loader
帮助我们删除 svg 里的fill
属性, 这样使得我可以自定义 svg 的颜色, 之前一旦被定好了颜色就修改不了.
# 写一个 Icon 组件
在开始写代码前, 先不要管具体的实现细节. 而是想我在使用这个 Icon 组件时的写法:
<Icon name="money" />
Copied!
1
上面的形式是最简单也是最简洁的.
# 开始实现
Icon 组件的模板很容易写:
<template> <svg class="icon"> <use :xlink:href="`#${name}`"></use> </svg> </template> <script lang="ts"> export default { name: "Icon", props: ["name"] }; </script> <style scoped> /* iconfont推荐的默认样式 */ .icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; } </style>
Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
最主要的问题是如何一次性导入所有的 icon 到组件里以方便复用, 下面是解决代码:
const importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext); try { importAll(require.context("../assets/icons", true, /\.svg$/)); } catch (e) { console.log(e); }
Copied!
1
2
3
4
5
6
7
2
3
4
5
6
7