# 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;
}
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 目录
}
};
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" />
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>
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);
}
1
2
3
4
5
6
7
2
3
4
5
6
7