Vue3从0到1组件开发-基础组件:Icon图标库

3,350 阅读5分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

必不可少:图标库

它真的必须吗?

21世纪已经过去了20年了,前端也已经发展了20多年了,随着用户的审美越来越高,对用户体验的要求也越来越高,我想已经很少在主流网站中找到一个不用图标的网站了吧?

而最开始的图标多以图片为主,后为了优化减少请求有了雪碧图的概念,但它仍然是图片,图片的加载始终是较慢的。之后有了svg,才终于好了一点,但是也使用起来也并不方便,零零散散的。

而随着阿某推出iconfont网站之后,字体图标替代了图片图标的地标,不过有一部分仍是使用svg的图标。

雪碧图: 多张小图合并在一张图片上,通过background-position属性控制限制区域。

优点:减少请求

缺点:只适合小图,且扩展性差。

image.png

(网图,侵删)

那么回到主题,它真的必须吗?

从大小来看,一张图片的尺寸是固定的,并且大小起步在2K以上,但是在大屏上就会糊。

从自愿请求来看,字体图标库是直接引入在项目中,而图片图标需要多次请求。

从便捷角度来看,字体图标可以通过一个别名直接引用,而图片则需要写一串地址。

不过需要注意的一点事,iconfont上面的图标理论来讲是属于别人家的孩子,你拿回去装一下自己的孩子还行,但如果要向这世界宣布它是你的娃了(商用),还是需要和其亲生父母办个领养手续的(授权)

不想领养也没关系,今天的文章就是学习下如果自己造一个娃出来,自己学会造娃了之后,还怕没有娃?

当然怕,自己不会美工或者没有美工,也是巧妇难于无米之炊。

怎么造呢?

美工这一块,当然是需要自己想办法了,本文只是负责告诉你要怎么造一个健康一致的小宝宝。

健康: 指能正常使用的字体图标;

一致:图标只存一致,美观就得看个人发挥了。

前戏

首先是准备Adobe Illustrator一只,然后来到iconfont-帮助中心

如下图找到.ai文件,点击后下载,将模板文件下载至本地。

image.png

下载完成之后,使用AI软件打开,在本地将要制作成图标库一员的图标丢进去,并按照网站中的引导,拉伸到同样大小,不用担心导出后大小的问题,因为导出后是svg的文件,比较小,而最后会做成字体,更小。

到这一步,就有了一个和统一尺寸的svg图片,如果这之前的内容你觉得作为前端不需要懂的话,那我建议你拉设计注册个掘金账号来看,顺便多给我点个赞,嘻嘻嘻;

备战

现在我们有了一个已经准备好融入图标库的图标了,那么我们就该开始第二部,把它们制作成一个字体文件了。

打开另一个网站iconmoon.io,接下来的从svgttf的工作将在这里完成。

打开之后可以看到是一个默认的图标库,不用理它,如图,清空默认的库。

image.png

清空之后,点击上面的紫色按钮Import Icons,添加刚刚做好的图标。

新添加的图标如左边的样式,需要点击一下,之后如右图,选中的样式代表是确认添加的

image.png

然后点击右下角来到如图所示的界面,在图标这里可以设置一个名字,我配置为common-star,即后面在项目中使用的图标名。

配置好之后,点击右下角的download就可以下载下来。

image.png

下载下来之后,可以看到有如下几个文件,其中的json文件可以用来重新导入这个图标。

fonts目录中就有了我们最终生成的字体文件了。

image.png

成库

前期的准备工作都做好了。接下来就是把他做成一个图标库了。

iconfont不同,iconfont已经是导入之后直接通过iconfont类名来使用。

而我这里要做的是把他做成一个图标库,使用时也是以组件的形势去使用。

先创建好文件结构

root/src/components
|
|-icons
    |-icons.js // 存储所有的字体图标别名
    |-icons.vue
    |-index.js // 导出
    |-iconmoon.ttf // 复制过来的字体库

先从简单的开始:

打开刚刚从iconmoon下载的压缩包,把字体文件复制过来。

OK,结束。 nice!


然后的复杂一丢丢的

打开icons.js文件

export default {
 // 键名是引用时的名字, 后面的值是字符编码, 手动加`\u`,再复制iconmoon那边生成的字符实体
    "common-star": "\ue900" 
}

然后在再复杂一点点的。 这里直接贴代码

<template lang="pug">
block content
div(
  class="yx-icons" 
  @click="onClick"
  :style="{ 'color': color, 'font-size': `${size}px`, 'height':`${size}px` }"
) {{ icons[type] }}
</template>

结构部分就是简单渲染的一下而已, 主要是看js部分的值

<script setup>
import {defineEmit, defineProps, reactive} from 'vue';
import iconsList from './icons.js';

const emits = defineEmit(['click']);
const props = defineProps({
  type: {
    type: String,
    default: ''
  },
  color: {
    type: String,
    default: '#333333'
  },
  size: {
    type: [Number, String],
    default: 16
  }
});
// 引入刚刚写好的icon.js,返回的对象用于渲染图标
const icons = reactive(iconsList);
// 有些情况下,需要添加图标的点击事件。
const onClick = (e) => {
  emits('click');
}
</script>

css部分也比较简单,直接贴出来,做一个自定义的字体,这个字体就是用刚刚的图标字体文件。

<style lang="scss" scoped>
@font-face {
	font-family: yxicons;
	src: url('./icomoon.ttf') format('truetype');
}

.yx-icons {
	display: flex;
	justify-content: center;
	align-items: center;
	font-family: yxicons;
}
</style>

最后的最后

到此为止,我们已经学会如何造一个娃了,试试喊上设计大佬来看这篇文章前半部分,然后自个儿完成后半部分了。

俗话说: 啥啥搭配,干活不累。

希望各位大佬能快乐工作,认真生活。