最近参与的cmdb(配置管理数据库)项目中使用了大量的图标,在之前一直都是使用雪碧图,也就是将各种图标全部放到一张大图中,然后再使用CSS切图的方式读取。前段时间接触到字体图标,瞬间被它的强大所吸引,所以这次改用Iconfont来实现。

Iconfont简介

不论是压缩后的图片,还是雪碧图,终归都是图片,只要是图片,在网络传输中都会占用大量的资源,但是字体图标的诞生,可以极大的减少这一部分占用的资源。
对于字体图标,个人最喜欢的还是阿里矢量图标库Iconfont,里面有大量的图标,而且使用的方式也很简单。
关于Iconfont的使用,可以参考Iconfont帮助中心,文章中讲述的很详细,今天我们主要来说说Symbol引用。

Symbol引用

相比于其余两种用法,个人更倾向于Symbol的使用,相比于其余两种方式的引用,Symbol有以下的优点:

  • 支持多色图标了,不再受单色限制。
  • 通过一些技巧,支持像字体那样,通过font-size,color来调整样式。
  • 使用更加便捷。

应用场景

最近有一个需求,用户在创建模型时,需要选择模型的图标(将近60多个图标),然后将图标存到数据库中,模型展示时从数据库读取并展示在页面上。

这个需求并不难,最常用的思路就是找60多张图片,然后在用户选择图标的时候加载这些图片就行了,考虑到性能问题,将图片合并成雪碧图,一次请求然后使用css定位读取就行了。的确这种方案如果我没接触过Iconfont我或许就会这么实现,但是现在有了Iconfont实现可以更简单。

1.首先我们去Iconfont中找到自己需要的图标,并添加到到自己的项目中

2.在项目中,选择Symbol,然后生成代码,注意代码是一个JS文件

3.在Vue项目中封装一个Icon组件

  • 组件
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
export default function createIconfont(options) {
let scriptUrlList = options.scriptUrl;

// 将第二步生成的js文件插入到DOM中
for (let scriptUrl of scriptUrlList) {
if (
document !== 'undefined' &&
typeof window !== 'undefined' &&
typeof document.createElement === 'function' &&
typeof scriptUrl === 'string' &&
scriptUrl.length
) {
let script = document.createElement('script');
script.setAttribute('src', scriptUrl);
script.setAttribute('data-namespace', scriptUrl);
document.body.appendChild(script);
}
}

// 加载图标的所有CSS样式
// 可能有多个,可能以数组的形式传递
const iconClass = function(className) {
let classObj = ['icon-font'];
if (Array.isArray(className)) {
for (let item of className) {
classObj.push(item);
}
} else if (className) {
classObj.push(className);
}
return classObj.join(' ');
};

return {
functional: true,
name: 'Icon',
render: function(h, context) {
let props = context.props,
listeners = context.listeners,
data = context.data;
return h(
'svg',
{
style: data.style,
class: iconClass(props.className),
on: listeners
},
// 第二步生成js之前需要将图标前缀去掉,Iconfont默认图标`icon-`
// 如果没有去掉,需要修改为[h('use', { attrs: { 'xlink:href': `#${icon-}` + props.type } })]
[h('use', { attrs: { 'xlink:href': '#' + props.type } })]
);
}
};
}
  • 注册全局组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import createIconfont from './createIconfont';
import { getHost } from '@/utils/common';

// 从外置配置文件中读取JS文件
// 避免图标修改样式后需要重新打包发布
const IconCite = createIconfont({
scriptUrl: getHost('VUE_APP_ICON_URL')
});

const icon = {
// 注册全局组件icon
install(Vue) {
Vue.component('icon', IconCite);
}
};

export default icon;

完成了上述步骤,在项目中我们就可以看到一个个的Symbol标签。

4.构建图标信息列表

虽然我们可以不用讲图标文件导入项目中,但是我们还是需要知道页面上应该显示哪些图标。

增加一个title主要是为了检索是方便。
这一部分可以根据项目提供的文档很快解决

5.遍历第4步中的数据生成即可

1
2
3
4
5
6
7
8
9
10
11
12
13
<el-carousel v-show="!isSearch" trigger="click" :autoplay="false" arrow="always">
<el-carousel-item v-for="v in 3" :key="v">
<div class="list_group icon_page">
<div v-for="(item, index) of iconsMap(v - 1)" :key="index" @click="onCheckedIcon(item)">
<el-tooltip :content="item.title" placement="top">
<div class="icon_item" :class="[item.icon === modelIcon ? 'icon' : '']">
<icon :type="item.icon" />
</div>
</el-tooltip>
</div>
</div>
</el-carousel-item>
</el-carousel>

6.最终实现效果

以上就是完整步骤,不知道对你有没有帮助呢


本文完