React造轮子(reacthook实现一套自己的组件库)轮子公开课——第五课【Radio、RadioButton、RadioGroup】组件

本文详细介绍了基于React构建的UI组件库中Radio、RadioButton和RadioGroup组件的实现逻辑和流程。讨论了两种实现单选框组件的方法,并提供了代码详解,包括Radio组件的样式和逻辑处理,RadioButton组件的样式定制以及RadioGroup组件如何封装以实现选项组功能。同时,文章还展示了组件的样式和功能效果。

一、组件库介绍

有兴趣的同学 可以先着手看源码,之前写的一系列开源组件库项目(有帮助的同学也帮忙点个star👍)

名称 官网 github
tinkerbell-ui(vue2.0) http://tinkerbell.top https://github.com/hanbingxu82/tinkerbell-ui
tinkerbell-ui(vue3.0) https://github.com/hanbingxu82/tinkerbell-ui-next
tinkerbell-ui(react-hook) https://github.com/hanbingxu82/tinkerbell-ui-react

二、Radio、RadioButton、RadioGroup组件流程介绍

在一个ui组件库当中其实,表单组件可以称之为重中之重,因为现在基本上pc端大部分开发还是面向的b端,所以基本上表单组件,在每个小模块当中是基本上都可以使用到的,那么关于 radio 组件我相信大家也都很熟悉,因为不免得每个表单中基本都带有着单选框组件,像如下,其实本身html标签的input的type给个radio属性也就是最初始的单选组件
在这里插入图片描述
那么我们现在肯定也要捋清楚一个逻辑就是我们怎么去实现这个radio单选框组件呢?其实有两种思路:


1、我们采用一个div去做底层,然后给这个div去设置样式,实现对应的点击事件,触发回显值,对应点击设置高亮等。但是这样也有弊端就是什么,我们外层绑定一个原始的form是无法提交表单值的、再有无法抓取value值、无法使用fieldset进行统一禁用这些,表单的原始功能就无法模拟了。

2、我们采用 input type=“radio” 去做一个底层,当然因为本身也是携带着radio样式的,这样我们只需要改样式即可,然后同样的本身也带有着点击事件默认行为等,我们直接使用默认的一系列方法即可


所以综上所述,我们的 radio 组件底层既采用 input type=“radio” 去实现功能,再有像RadioButton的话,我们也可以做一个简单的组件封装,底层我们还是一样的,就是设置边框以及选中高亮这些实现对应的功能,再有至于RadioGroup的话,总的来说它是用来包裹 Radio 、RadioButton组件的,我们可以直接在这个组件上面设置默认的选中值,以及回传值,以此来实现功能,所以接下来我们总结功能:

Radio:
type: string // type类型 判断颜色
checked: boolean // 是否选中
disabled: boolean // 禁用项
groupValue: any // groupValue 值是否与value值相等 逻辑上来说可传可不传 当时只是为了做判断用的 因为 value 也同样可以给与初始值
value: any // value初始值
label: string // 初始 lable 文本
name?: string // 原生 name 属性


RadioButton:
type: string // type类型 判断颜色
checked: boolean // 选中状态
disabled: boolean // 禁用状态
groupValue: any // groupValue 值是否与value值相等 逻辑上来说可传可不传 当时只是为了做判断用的 因为 value 也同样可以给与初始值
label:string, // 初始 lable 文本
value: any // value初始值
name?: string // 原生 name 属性
size: string // 按钮大小
buttonStyle: string // style样式


RadioGroup:
name?: string // 统一原生name值
buttonStyle: string // 如果是button类型 统一的buttonStyle
disabled: boolean // 统一禁用
options: any // js编程式组件
optionType: string // js编程式类型
size: string // 大小
value: any // value值

在这里也是讲解一下 RadioGroup 的options,js编程式的组件,在这里其实也是参考了antd传入options,然后实现组件功能,随机我们也在我们的组件库当中去实现此功能。
在这里插入图片描述

三、代码详解

3.1、Radio.tsx

import React from 'react'
import './index.scss'

const classnames = require('classnames')
interface Iprops {
   
   
  type: string // type类型 判断颜色
  checked: boolean // 是否选中
  disabled: boolean // 禁用项
  groupValue: any // groupValue 值是否与value值相等 逻辑上来说可传可不传 当时只是为了做判断用的  因为 value 也同样可以给与初始值
  value: any // value初始值
  label: string // 初始 lable 文本
  name?: string // 原生 name 属性
}
function Radio(props: any) {
   
   
  const {
   
   
    type = 'default',
    disabled = false,
    groupValue,
    checked = false,
    value,
    label,
    name
  }: Iprops = props
  function handleChange(evt: any) {
   
   
    props.onChange && props.onChange(evt.target.value)
  }
  return (
    <div
      className={
   
   [
        'tb-radio',
        classnames({
   
   
          'is-disabled': disabled
        })
      ].join(' ')}
    >
      <label>
        <input
          type='radio'
          checked={
   
   groupValue ? (groupValue == value ? true : false) : checked}
          name={
   
   name}
          disabled={
   
   disabled}
          onChange={
   
   handleChange}
          value={
   
   value}
          className={
   
   [
            `radio-type_${
     
     type}`,
            classnames({
   
   
              'is-disabled': disabled
            })
          ].join(' ')}
        />
        <span>{
   
   props.children ? props.children : label ? label : value}</span>
      </label>
    </div>
  )
}
export default Radio

3.2、Radio / index.scss

@import '../../style/variables.scss';


$type:('success', 'primary', 'danger', 'warning', 'info', 'default');

@function typeFunction($t) {
   
   
  @if $t==success {
   
   
    @return $color-success
  }

  @else if $t==primary {
   
   
    @return $color-primary
  }

  @else if $t==info {
   
   
    @return $color-info
  }

  @else if $t==danger {
   
   
    @return $color-danger
  }

  @else if $t==warning {
   
   
    @return $color-warning
  }

  @return $color-primary
}

@function typeDisabledFunction($t) {
   
   
  @if $t==success {
   
   
    @return $color-success-light2
  }

  @else if $t==primary {
   
   
    @return $color-primary-light2
  }

  @else if $t==info {
   
   
    @return $color-info-light2
  }

  @else if $t==danger {
   
   
    @return $color-danger-light2
  }

  @else if $t==warning {
   
   
    @return $color-warning-light2
  }

  @return $color-primary-light2
}

.tb-radio {
   
   
  display: inline-block;

  label {
   
   
    display: flex;
    align-items: center;
  }
}

@each $t in $type {
   
   
  .radio-type_#{
   
   $t} {
   
   
    width: 20px;
    height: 20px;
    appearance: none;
    position: relative;
    outline: none;
    vertical-align: bottom;
    cursor: pointer;
  }

  
评论 15
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

归来巨星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值