likes
comments
collection
share

vue3基础组件开发-button(按钮组件)

作者站长头像
站长
· 阅读数 9

前言

使用了vue3有很长一段时间了,写了很多的基础组件在自己使用,整理一下(尽量使用最简单的方式实现),当做对自己知识的梳理。

tips:button组件可以说是,几乎每个前端必定会写的组件之一,所以本篇更多的是对思路的梳理。

技术栈

vue3 + tailwindcss + ts

页面开发

  1. html结构

    <-- 按钮主体 -->
    <button>
        <-- 左边logo -->
        <i></i>
        <slot>
          {{ title }}
        </slot>
        <-- 右边logo -->
        <i></i>
    </button>
    

    一个button的组件的页面开发可以说就到这里了,剩下的无非就是调整button的样式了

逻辑开发

  1. 根据type类型决定button的样式

    • 我们使用组件库的时候经常会看到这样的用法,通过在组件上传一个字符串控制button的样式
      <el-button type="primary">Primary</el-button>
      
    • 实现上面功能的主要逻辑如下:
      • 通过props获取到type的值
      • 建立一个map对象
      • 在map里面存对应type数据
      • 通过计算属性获取到map返回的值
      • 通过动态class插入
      interface Props {
        type?: string
      }
      
      const props = withDefaults(defineProps<Props>(), {
        type: '',
      })
      
      const colorMap = new Map()
        .set('', '')
        .set('default', 'border')
        .set('primary', 'border bg-[#409EFF]')
        .set('success', 'border bg-[#67C23A]')
        .set('info', 'border bg-[#909399]')
        .set('warning', 'border bg-[#E6A23C]')
        .set('danger', 'border bg-[#F56C6C]')
      
      const typeColor = computed(() => colorMap.get(props.type))
      
      vue3基础组件开发-button(按钮组件)
  2. 自定义样式

    在大多中小公司的前端研发中,整个设计没有形成整体化;或者说是,在上层(老板)的干预下,设计体系今天抄一下这个,明天抄一下那个;所以,类似很多组件库中流行的预设模板之类的方式行不通。

    举个例子:比如说我固定了圆角是4px,或者设置了大中小三个样式,4px、8px、12px,但是设计不按照这样的圆角去设计,搞个5px、2px或者其它圆角。

    这样的情况,通常的处理方式是,通过覆盖css的方式去实现,比如说我用了element组件库,那么我就覆盖element组件,在vue中可能还会经常用到css深度选择器区覆盖。

    当然,随着技术的发展,组件库通常有覆盖样式的方案,比如说,通过一个 $xxx 的变量去改变整个的颜色之类的东西。但是,有一个问题是,你必须要用这个组件库,或者说你还要学习如何去配置。

    那么,在vue3中,可以用另外一种方式去覆盖样式,也就是透传 Attributes 来实现。毕竟,在中国,组件库最少几十个,但是流行的前端开发框架就两个,一个vue,一个react,因为上手难度的原因,在中小公司,你接触到的基本都是vue。

    透传 Attributes使用如下,以本篇文章的button按钮为例:

    • 子组件本身不设置过多的预设样式模板
    • 在父组件中引入子组件
    • 直接在被引入的子组件身上写class样式
    • 如下图所示,直接写的样式,会透传到子组件身上,并且同样的样式会覆盖子组件(根据css的渲染顺序) vue3基础组件开发-button(按钮组件) vue3基础组件开发-button(按钮组件) vue3基础组件开发-button(按钮组件)
  3. 显示icon

    • 我们平常封装组件的木的是为了什么呢?是为了复用,所以在现在vue3的技术中,如果没有设计各种给按钮加icon的需求,那么可以说,在使用透传之后,可以不必要封装button组件;大多数的设计师的设计里,你封装了css,用的时候还是要再写一遍css。
    • 所以,button组件在我的理解中,更多的是封装各种icon用的;因为,封装了,确实能够少写很多的 i 标签。
    • 具体思路是:
      • 在button中间放个插槽
      • 两边各放一个i标签
      • 给props传参加上两个参数,left和right
      • 给i标签加上判断,哪个有值就显示哪个
      • 中间的插槽是为了,你自定义标签使用
      • 整个方案结合iconfont最佳食用
      <template>
        <button :class="typeColor">
          <i v-if="props.left"></i>
          <slot> 按钮 </slot>
          <i v-if="props.right"></i>
        </button>
      </template>
      
      <script setup lang="ts">
      interface Props {
        type?: string
        left?: string
        right?: string
      }
      
      const props = withDefaults(defineProps<Props>(), {
        type: '',
        left: '',
        right: '',
      })
      
      const colorMap = new Map()
        .set('', '')
        .set('default', 'border')
        .set('primary', 'border bg-[#409EFF]')
        .set('success', 'border bg-[#67C23A]')
        .set('info', 'border bg-[#909399]')
        .set('warning', 'border bg-[#E6A23C]')
        .set('danger', 'border bg-[#F56C6C]')
      
      const typeColor = computed(() => colorMap.get(props.type))
      </script>
      

尾声

很多人认为重复写组件是造轮子,确实,市面上有很多非常成熟非常好的组件库提供使用。但是,我想说的是,前端最快的成长路径就是造轮子,造轮子从组件库开始。而且,你不知道你会遇到什么设计或者产品,你会发现,市面上没有哪一个的组件库是完全合用的,还是需要二次开发(这也是为啥网上很多二次封装xxx组件的文章很多的原因之一),或者自己写组件。

水平有限,如有错漏之处,欢迎大佬指正。