【Nova UI】九、打造组件库第一个组件-图标组件(中):属性、功能与样式的完美融合

序言

在上一篇文章中,我们成功搭建起 SVG 图标组件包的基础架构🏗️,这如同为组件库这座大厦奠定了稳固的基石。如今,我们将目光聚焦于图标组件样式的雕琢工作,思考如何巧妙运用已掌握的 SASS 全局变量管理技巧,赋予图标组件丰富多样且统一协调的外观风格🌈。这不仅是提升组件库视觉一致性的关键🔑,更是增强用户体验的重要一环。让我们一同开启这场图标组件的样式优化之旅🚶‍♂️。

Icon组件

在组件库的持续建设中,Icon 组件的开发是极为关键的一步🌟。为实现对图标组件属性及类型的精准把控,我们在packages/components/icon/src/目录下,新增了icon.tsicon.js文件。其中,icon.ts肩负着定义组件属性与 TypeScript 类型的重任。

icon.ts 剖析
import { ExtractPropTypes, PropType } from 'vue'
import { svgs } from '@nova-ui/svgs'

export const iconProps = {
  name: {
    type: String as PropType<(typeof svgs)[number]>,
    required: true,
  },
  color: {
    type: String,
  },
  size: {
    type: [Number, String] as PropType<number | string>,
  },
} as const

export type IconType = ExtractPropTypes<typeof iconProps>

这段代码构建了 Icon 组件的基础属性体系📋。name属性指定图标名称,其取值限定在svgs数组内,确保只有预定义图标可被调用,避免非法名称的使用,就像给图标选择设置了一个 “白名单”🛂。color属性允许开发者通过字符串形式的颜色值对图标进行个性化上色🎨,轻松满足不同的视觉需求。size属性设计灵活,既支持数字形式(默认单位像素),也接受字符串形式的尺寸描述,满足不同场景下对图标大小的精确调整需求,无论是在小巧的移动端界面还是宽大的电脑屏幕上,都能完美适配📱🖥️。

PropType
是 Vue 中用于精确定义组件props类型的工具,通过它可指定复杂属性类型,增强 TypeScript 开发时的类型安全性。\

const MyComponent = defineComponent({
  props: {
    value: {
      type: [String, Number] as PropType<string | number>,
      required: false
    }
  },
  setup(props) {
    return () => <div>{props.value}</div>;
  }
});

在上述代码中,value属性可接受stringnumber类型的值,就像给组件的这个 “输入口” 明确了可接收的 “货物种类”🛒。

ExtractPropTypes
用于从props定义对象中提取属性类型信息,同样增强组件的类型安全性。\

const props = {
  message: {
    type: String,
    required: true
  }
};
const MessageComponent = defineComponent({
  props,
  setup(props) {
    return () => {
      return <div>{props.message}</div>;
    };
  }
});
type Props = ExtractPropTypes<typeof props/>;
const App = defineComponent({
  setup() {
    const myMessage = 'Hello, Vue 3!';
    return () => {
      return <MessageComponent message={myMessage} />;
    };
  }
});

在此例中,TypeScript依据ExtractPropTypes提取的Props类型,检查传递给MessageComponentmessage属性是否符合要求,确保数据传递的准确性和稳定性📡。

icon.vue 解析

icon.vue文件在 Icon 组件整体构建中,承担着实现具体功能的核心任务🧠。

<template>
  <i
    :class="ns.b()"
    :style="style"
  >
    <component :is="svg" />
  </i>
</template>

在 template 里,<i> 标签作为图标容器,通过 :class 绑定 ns.b() 生成的特定类名,利用 useNamespace 避免样式冲突。:style 绑定 style 计算属性,用于动态调整图标样式。而 <component :is="svg" /> 依据 svg 计算属性,能动态渲染出对应 SVG 图标组件,增强了复用性与灵活性🎭。

<script lang="ts" setup>
  import { computed, CSSProperties } from 'vue'
  import { useNamespace } from '@nova-ui/hooks'
  import { isUndefined, addUnit } from '@nova-ui/utils'
  import * as Svgs from '@nova-ui/svgs'
  import { iconProps } from './icon'

  const ns = useNamespace('icon')
  defineOptions({
    name: 'NIcon',
  })
  const { name, color, size } = defineProps(iconProps)

  const svg = computed(() => {
    return Svgs[name]
  })

  const style = computed<CSSProperties>(() => {
    if (!color && !size) return {}

    return {
      fontSize: isUndefined(size) ? undefined : addUnit(size),
      color: color,
    }
  })
</script>

script部分,通过导入各种必要的模块与工具🛠️,为组件的功能实现提供了有力支持。computed用于创建计算属性,CSSProperties定义样式类型,useNamespace生成命名空间类名,isUndefinedaddUnit分别判断值是否为undefined及添加单位。同时,还导入了 SVG 图标组件与组件属性。

ns 通过 useNamespace 生成 Icon 组件的命名空间实例📍。defineOptions 定义组件名称为 NIcon。通过解构 defineProps(iconProps) 获取父组件传来的 namecolorsize 属性🍱。

svg 计算属性依据 name 从 Svgs 获取对应图标组件,style 计算属性根据 color 和 size 生成样式对象。若无这两个属性传入则返回空对象,否则为 size 添加单位并设置 fontSize 和 color 样式✨。

icon.vue 以简洁代码实现高效功能,为 Icon 组件在库中的应用与扩展筑牢根基。部分工具函数实现可在下方提及到的仓库中查看 。

样式

packages/theme-chalk/src目录下,新增icon.scss,用于编写 Icon 组件的样式。再在当前目录下新增index.scss统一导入所有组件样式。

@use 'mixins' as *;

@include b(icon) {
  display: inline-flex;
  width: 1em;
  height: 1em;
}

这段样式代码为 Icon 组件设定了基础的展示样式,使其以inline-flex的布局方式呈现,宽度和高度均为1em,确保图标在页面上能够整齐、美观地展示🛍️。

到此,图标组件已经实现完成了🎉。通过从属性定义到功能实现,再到样式设计的一系列精心打造,我们成功地为组件库增添了一个实用且美观的 Icon 组件,为后续的开发工作奠定了更加坚实的基础。

🦀🦀感谢看官看到这里,如果觉得文章不错的话🙌,点个关注不迷路⭐。
诚邀您加入我的微信技术交流群🎉,群里都是志同道合的开发者👨‍💻,大家能一起交流分享摸鱼🐟。期待与您在群里相见🚀,咱们携手在开发路上共同进步✨ !
👉点我

感谢各位大侠一路相伴,实在感激! 不瞒您说,在下还有几个开源项目 📦,它们就像精心培育的幼苗 🌱,急需您的浇灌。要是您瞧着还不错,麻烦动动手指,给它们点亮几颗 Star ⭐,您的支持就是它们成长的最大动力,在此谢过各位大侠啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值