TS+react自建组件库 01
Hello World组件测试
import {FC} from 'react' interface IHello { message?: string; } const Hello:FC<IHello> = function(props){ let {message} = props; return ( <h2>{message}</h2> ) } Hello.defaultProps = { message : 'Hello World' } export default Hello;
点赞按钮组件测试
import {FC,useState} from 'react' const GiveLike:FC = () => { let [like, setLike] = useState(0); return ( <button onClick = {() => setLike(like + 1)}> 👍{like} </button> ) } export default GiveLike;
鼠标坐标组件测试
import {FC, useState, useEffect} from 'react' const MousePosition : FC = () => { const [positions,setPosition] = useState({x:0,y:0}) const updatePosition = (e:MouseEvent) => { setPosition({x:e.clientX,y:e.clientY}) } useEffect(() =>{ document.addEventListener('click',updatePosition) return( () => { document.removeEventListener('click',updatePosition) } ) }) return ( <div> 鼠标坐标:X:{positions.x},Y:{positions.y} </div> ) } export default MousePosition;
KGD的样式解决方案
①Inline CSS
②CSS in JS
③Sass/Less(KGD选择的解决方案)
样式系统文件结构:
styles/ _variables.scss //各种变量以及可配置设置 _mixins.scss //全局mixins _functions.scss //全局functions components/ Button/ index.scss //组件的单独样式 ...
KGD的色彩体系
系统色板 - 基础色板 + 中性色板
产品色板 - 品牌色 + 功能色
// 中性色彩 $white: #fff !default; // !default 关键字表示定义该变量后其不会被重新赋值 $gray-100: #f8f9fa !default; $gray-200: #e9ecef !default; $gray-300: #dee2e6 !default; $gray-400: #ced4da !default; $gray-500: #adb5db !default; $gray-600: #6c757d !default; $gray-700: #495057 !default; $gray-800: #343a40 !default; $gray-900: #212529 !default; $black: #000 !default; // 基础色板 $blue: #0d6efd !default; $indigo: #6610f2 !default; $purple: #6f42c1 !default; $pink: #d63384 !default; $red: #dc3545 !default; $orange: #fd7e14 !default; $yellow: #fadb14 !default; $green: #52c41a !default; $teal: #20c997 !default; $cyan: #17a2b8 !default; // 系统色板 $primary: $blue !default; $secondary: $gray-600 !default; $success: $green !default; $info: $cyan !default; $warning: $yellow !default; $danger: $red !default; $light: $gray-100 !default; $dark: $gray-800 !default;
KGD的样式变量分类
- 基础色彩系统
- 字体系统
- 表单
- 按钮
- 边框和阴影
- 可配置开关
tips:node-sass版本为5.0.0
Failed to compile. ./src/styles/index.scss (./node_modules/css-loFailed to compile. ./src/styles/index.scss (./node_modules/css-loFailed to compile. ./src/styles/index.scss (./node_modules/css-loFailed to compile. ./src/styles/index.scss (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-6-1!./node_modules/postcss-loader/src??postcss!./node_modules/resolve-url-loader??ref--5-oneOf-6-3!./node_modules/sass-loader/dist/cjs.js??ref--5-oneOf-6-4!./src/styles/index.scss) Node Sass version 6.0.1 is incompatible with ^4.0.0 || ^5.0.0. //版本不兼容,此时node-sass版本为6.0.1
KGD的第一个组件-Button
需求分析
类型分析-type:主按钮、默认按钮、危险按钮、链接按钮
大小分析-size:默认按钮、小型按钮、大型按钮
按钮状态:能否点击
样式:高亮,文字居中,颜色
设计实现
插件引入:classnames --一个简单的JavaScript工具,用于有条件地连接类名。
安装命令:yarn add classnames @types/classnames --save
使用方式:
classNames('foo', 'bar'); // => 'foo bar' classNames('foo', { bar: true }); // => 'foo bar' classNames({ 'foo-bar': true }); // => 'foo-bar' classNames({ 'foo-bar': false }); // => '' classNames({ foo: true }, { bar: true }); // => 'foo bar' classNames({ foo: true, bar: true }); // => 'foo bar' // lots of arguments of various types classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux' // other falsy values are just ignored classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
Button组件
import React, {FC} from 'react' import classNames from 'classnames' export enum ButtonType { Primary = 'primary', Danger = 'danger', Default = 'default', Link = 'link', } export enum ButtonSize { Large = 'lg', Small = 'sm', } interface BaseButton { className ?: string, btnType ?: ButtonType, size ?: ButtonSize, children ?: React.ReactNode, disabled ?: boolean, href ?: string, } type NativeButtonProps = BaseButton & React.ButtonHTMLAttributes<HTMLButtonElement> //获取button原本具有的属性并与自定义button组件类型合并 //交叉类型是将多个类型合并为一个类型 type AnchorButtonProps = BaseButton & React.AnchorHTMLAttributes<HTMLAnchorElement> //获取a原本具有的属性并与自定义button组件类型合并 type ButtonProps = Partial<NativeButtonProps & AnchorButtonProps> //映射类型:将一个已知的类型每个属性都变为可选的 const Button : FC<ButtonProps> = (props) => { const { className, btnType, size, children, disabled, href, ...restProps //获取所有原属性 } = props //className允许用户自定义className const classes = classNames('btn', className, { [`btn-${btnType}`] : btnType, [`btn-${size}`] : size, 'disabled' : btnType === ButtonType.Link && disabled, }) return btnType === ButtonType.Link && href ? ( <a className = {classes} href = {href} {...restProps} > {children} </a> ) : ( <button className = {classes} disabled = {disabled} {...restProps} > {children} </button> ) } Button.defaultProps = { disabled: false, btnType: ButtonType.Default } export default Button;