• 从0搭建Vue3组件库之Icon组件


    Icon组件想必大家都不陌生,本篇文章将为大家详细介绍Icon组件是如何实现的。如果你想了解完整的组件库搭建,你可以点击使用Vite和TypeScript带你从零打造一个属于自己的Vue3组件库。

    引入字体图标

    字体图标我们引用阿里的iconfont。首先注册登录然后进入 资源管理->我的项目->新建项目,如下图
    在这里插入图片描述

    我们将前缀改为我们组件库的名字(这里可以随便命名),后面我们的字体图标class前缀就是这里定义的。
    项目建好之后我们去 素材库下的图标库找一些自己喜欢的图标添加到购物车,然后再将我们购物车的图标添加至我们的项目中

    在这里插入图片描述
    在这里插入图片描述

    再回到我们的项目,将图标下载到我们本地,这里我们选择symbol方式引用
    在这里插入图片描述

    然后解压,这里我们只需要这些文件中的iconfont.js,我们将其复制放到我们的Icon项目下面,这里我将它放在Icon/font下。

    Icon组件中使用图标

    我们使用的是symbol方式引用,所以是使用是非常方便的。这是一种全新的使用方式,应该说这才是未来的主流,也是目前推荐的用法,它有一下特点

    • 支持多色图标了,不再受单色限制。
    • 通过一些技巧,支持像字体那样,通过font-size,color来调整样式。
    • 兼容性较差,支持 ie9+,及现代浏览器。
    • 浏览器渲染svg的性能一般,还不如png。

    首先我们要先引入通用css样式

    .icon {
           width: 1em; height: 1em;
           vertical-align: -0.15em;
           fill: currentColor;
           overflow: hidden;
        }
    复制代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里我们将其放在了Icon/style/index.less中
    然后在组件中使用:

     <svg class="icon" aria-hidden="true">
            <use xlink:href="kitty-xxx"></use>
        </svg>
    复制代码
    
    • 1
    • 2
    • 3
    • 4

    动态渲染

    因为我们的Icon需要支持传入不同name展示不同图标,所以我们需要将Icon组件完善一下
    首先在Icon/types中定义我们的props类型

    import { ExtractPropTypes } from 'vue'
    export const iconProps = {
        name: {
            type: String
        }
    
    }
    export type IconProps = ExtractPropTypes<typeof iconProps>
    
    
    复制代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    然后将icon.vue修改为

    <template>
        <svg class="icon" aria-hidden="true">
            <use :xlink:href="iconName"></use>
        </svg>
    
    </template>
     <script lang="ts">
     import './font/iconfont.js'
     import './style/index.less'
     import { defineComponent, computed } from 'vue'
     import { iconProps } from './types'
     export default defineComponent({
         props: iconProps,
         setup(props) {
             const iconName = computed(() => {
                 return `#kitty-${props.name}`
             })
             return {
                 iconName
             };
         },
     });
     </script>
    复制代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    此时我们就能根据不同name展示不同图标了

    组件引入Icon

    引入一个Icon就很简单了,只需要传入一个name即可,比如我们在example/App.vue中使用如下

    <template>
        <div>
            <Icon name="edit" />
            <Icon name="download" />
            <Icon name="forward" />
            <Icon name="history" />
            <Icon name="file" />
            <Icon name="link" />
            <Icon name="good" />
        </div>
    </template>
    <script lang="ts" setup>
    import { Icon } from 'kitty-ui'
    
    </script>
    <style lang="less">
    .icon {
        font-size: 36px;
        color: #666;
        margin-right: 20px;
    }
    </style>
    
    复制代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    显示效果如下图
    在这里插入图片描述

    徽标提示

    我们可以设置dot属性后,让我们图标右上角展示一个小红点;设置badge属性后,会在图标右上角展示相应的徽标,所以我们先给我组件加两个属性:dot,badge。types.ts如下

    import { ExtractPropTypes } from 'vue'
    export const iconProps = {
        name: {
            type: String
        },
        dot: {
            type: Boolean
        },
        badge: {
            type: String
        }
    }
    export type IconProps = ExtractPropTypes<typeof iconProps>
    
    复制代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    然后我们根据这两个属性来展示我们不同的徽标,icon.vue修改如下

    <template>
        <div class="kitty-icon">
            <svg class="icon" aria-hidden="true">
                <use :xlink:href="iconName"></use>
            </svg>
            <div v-if="dot" class="kitty-info" :class="styleDot">{{ badge }}</div>
        </div>
    </template>
     <script lang="ts">
     import './font/iconfont.js'
     import './style/index.less'
     import { defineComponent, computed } from 'vue'
     import { iconProps } from './types'
     export default defineComponent({
         props: iconProps,
         setup(props) {
             const iconName = computed(() => {
                 return `#kitty-${props.name}`
             })
             const styleDot = computed(() => {
                 return {
                     [`kitty-dot`]: props.dot && !props.badge
                 }
             })
             const badge = computed(() => {
                 return props.badge
             })
             return {
                 iconName,
                 styleDot,
                 badge
             };
         },
     });
     </script>
    复制代码
    
    • 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

    组件通过dot和badge来赋予徽标不同class,对应类名样式如下

    .kitty-icon {
      display: inline-block;
      position: relative;
      .kitty-info {
        position: absolute;
        top: 8px;
        right: 0;
        box-sizing: border-box;
        min-width: 16px;
        padding: 0 3px;
        color: #fff;
        font-weight: 500;
        font-size: 12px;
        line-height: 1.2;
        text-align: center;
        border: 1px solid #fff;
        border-radius: 16px;
        background-color: #ee0a24;
        transform: translate(50%, -50%);
      }
      .kitty-dot {
        width: 8px;
        min-width: 0;
        height: 8px;
        background-color: #ee0a24;
        border-radius: 100%;
      }
    }
    复制代码
    
    • 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

    App.vue中使用

    <template>
        <div>
            <Icon name="comment" />
            <Icon name="comment" dot />
            <Icon name="comment" dot badge="1" />
        </div>
    </template>
    <script lang="ts" setup>
    import { Icon } from 'kitty-ui'
    
    </script>
    <style lang="less">
    .kitty-icon {
        font-size: 36px;
        color: #666;
        margin-right: 20px;
    }
    </style>
    
    
    复制代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    最终展示效果
    在这里插入图片描述

    图标颜色

    Icon的color属性用来设置图标的颜色。这个比较好实现,这里直接通过style赋予图标颜色(不要忘记在types.ts中定义组件属性)

    //icon.vue
    <template>
        <div class="kitty-icon">
            <svg class="icon" :style="iconColor" aria-hidden="true">
                <use :xlink:href="iconName"></use>
            </svg>
        </div>
    </template>
     <script lang="ts">
     import './font/iconfont.js'
     import './style/index.less'
     import { defineComponent, computed } from 'vue'
     import { iconProps } from './types'
     export default defineComponent({
         props: iconProps,
         setup(props) {
             const iconColor = computed(() => {
                 return {
                     color: props.color
                 }
             })
             return {
                 iconColor
             };
         },
     });
     </script>
    复制代码
    
    • 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

    App.vue中使用

    <template>
        <div>
            <Icon name="favorite" color="red" />
            <Icon name="favorite" color="green" />
            <Icon name="favorite" color="blue" />
            <Icon name="favorite" color="yellow" />
        </div>
    </template>
    <script lang="ts" setup>
    import { Icon } from 'kitty-ui'
    
    </script>
    <style lang="less">
    .kitty-icon {
        font-size: 36px;
        color: #666;
        margin-right: 20px;
    }
    </style>
    
    复制代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    效果如下
    在这里插入图片描述

    最后

    到这里一个Icon组件基本也就开发完了,如果你想了解更多组件的实现,你可以关注Vite+TypeScript从零搭建Vue3组件库 - 东方小月的专栏 - 掘金 (juejin.cn),将不定期的更新一些组件的实现。同时如果你发现文中有错误的地方或者有其它改进的地方欢迎指出,大家一起学习。

    源码附件已经打包好上传到百度云了,大家自行下载即可~

    链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27
    提取码: yu27
    百度云链接不稳定,随时可能会失效,大家抓紧保存哈。

    如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~

    开源地址

    码云地址:
    http://github.crmeb.net/u/defu

    Github 地址:
    http://github.crmeb.net/u/defu

    链接:https://juejin.cn/post/7122622920433598471

  • 相关阅读:
    pythony异常处理/catalan数和出栈排列数
    为什么需要对jvm进行优化,jvm运行参数之标准参数
    Go实战学习笔记-1.2基础语法:变量、常量、包、指针等
    java基于微信小程序的在线购物商城系统 uniapp 小程序
    需求解析思路
    flink-sql所有语法详解
    力扣第1005题 K 次取反后最大化的数组和 c++ 贪心 双思维
    Kubernetes技术与架构(七)
    上周热点回顾(8.22-8.28)
    计算机毕业设计ssm校园招聘管理系统968b0系统+程序+源码+lw+远程部署
  • 原文地址:https://blog.csdn.net/qq_39221436/article/details/125911820