react结合typescript 封装组件实例详解

 更新时间:2023年04月14日 14:56:22   作者:snail快跑  
这篇文章主要为大家介绍了react结合typescript 封装组件实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

项目环境搭建

项目依赖

创建支持 TypeScript 的 React 项目

npx create-react-app my-demo --template typescript

根据 typescript 官网文档的说明,还可以使用下面的命令

npx create-react-app my-demo --scripts-version=react-scripts-ts

css样式初始化的插件

npm install --save normalize.css

处理scss文件

npm install node-sass --save

一个简单的、有条件的绑定多个 className 的 JavaScript 实用函数

npm install classnames

@types 支持全局和模块类型定义

npm install @types/classnames --save

项目目录结构

my-demo
  |—— node_modules
  |——	public
  |     └─ favicon.ico
  |     └─ index.html
  |     └─ manifest.json
	|—— src
	|		 └─ ...
  |─   .gitignore
  |─   package.json
  |─   package-lock.json
  |─   README.md
  └─   tsconfig.json //文件中指定了用来编译这个项目的根文件和编译选项

创建一个组件

在项目中 删除src目录下除src/index.tsx之外所有的文件

import React from 'react';
import ReactDOM from 'react-dom/client';
import Hello from './src/Hello'
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <div>hellow TS</div>
);

在src下创建 Hello.tsx文件

import React form 'react'
//声明 Hello 组件 props 接口类型
interface BaseProps {
  message?:string //可选填 string 类型
}
const Hello:FunctionComponent<BaseProps> =(props) => {
    /*
      FunctionComponent<BaseProps> 接口,接收一个泛型
      	+ 使用 interface 定义的 BaseProps j接口作为泛型值
        + 组件还可以接收 props.chilren 属性接收组件实例传入的子节点
        + 使用 defaultProps 为 props 对象中属性设置初始化值
        + React.FunctionComponent 可以简写为 const Hello: FC<BaseProps> = (props) => {}
    */
    return <h1>{props.message}</h1>  
}

在终端执行 npm start启动项目查看结果

封装一个Button组件

Button按钮需求分析

依赖

classnames: 一个简单的 JavaScript 实用程序,用于有条件地将 classNames 连接在一起

$ npm install classnames --save

$ npm install @types/classnames --save //@types 支持全局和模块类型定义

用于编译css

npm install node-sass --save

classnames 使用示例

/* 与Node.js、Browserify或webpack 一起使用: */
var classNames = require('classnames');
classNames('foo', 'bar'); // => 'foo bar'
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'
/* 与 React.js 一起使用 */
/* 这个包是 的官方替代品classSet,它最初是在 React.js 插件包中提供的。
它的主要用例之一是使动态和条件className道具更易于使用(尤其是比条件字符串操作更简单)。因此,您可能有以下代码来className为<button>React 中的a生成道具: */             
class Button extends React.Component {
  // ...
  render () {
    var btnClass = 'btn';
    if (this.state.isPressed) btnClass += ' btn-pressed';
    else if (this.state.isHovered) btnClass += ' btn-over';
    return <button className={btnClass}>{this.props.label}</button>;
}
}
/* 您可以将条件类更简单地表示为一个对象: */
var classNames = require('classnames');
class Button extends React.Component {
  // ...
  render () {
    var btnClass = classNames({
      btn: true,
      'btn-pressed': this.state.isPressed,
      'btn-over': !this.state.isPressed && this.state.isHovered
    });
    return <button className={btnClass}>{this.props.label}</button>;
}
}
/*因为您可以将对象、数组和字符串参数混合在一起,所以支持可选的classNameprops 也更简单,因为结果中只包含真实的参数: */
var btnClass = classNames('btn', this.props.className, {
  'btn-pressed': this.state.isPressed,
  'btn-over': !this.state.isPressed && this.state.isHovered
});

在src新建components/Button/buttom.tsx组件

import React,{  ButtonHTMLAttributes, AnchorHTMLAttributes, FC } from 'react'
import classNames form 'classnames'
//声明按钮尺寸-枚举
export enum ButtonSize {
    Large = 'lg',
    Small = 'sm'
}
//声明按钮样式-枚举
export enum ButtonType{
  	Primary = 'primary',
    Default = 'default',
    Danger = 'danger',
    Link = 'link'
}
//声明按钮组件 props 接口
interface BaseButtonProps {
  className?: string;
  /*设置 Button的禁用*/
  disabled?:boolean;
  /*设置 Button的尺寸*/
  size?:ButtonSize;
  /*设置 Button 的类型*/
  btnType?:ButtonType;
  children: React.ReactNode; //ReactNode reactnode节点
  /*设置A标签href的类型*/
  href?:string;
}
//声明按钮与超链接标签的原生事件
type NativeButtonProps = BaseButtonProps & ButtonHTMLAttributes<HTMLElement>
type AnchorButtonProps = BaseButtonProps & AnchorHTMLAttributes<HTMLElement>
export type ButtonProps = Partial<NativeButtonProps & AnchorButtonProps>
export conast Button:FC<ButtonProps> = (props) =>{
  const {
    btnType, //传递进来按钮样式属性
    className, //传递进来自定义样式属性
    disabled, //传递进来是否禁用属性
    size,
    children,
    href,
    ...restProps  //解析按钮与超链接的原生事件属性
  } = props;
  /*样式拼接处理*/
  const classes = classNames('btn', className, {
  	/*[`btn-${btnType}`] : boolean
      boolean:
        + 为真返回 [`btn-${btnType}`]
        + 为假 不返回任何内容
    */
    [`btn-${btnType}`]: btnType,
    [`btn-${size}`]:size,
    'disabled':(btnType === 'link') && disabled //如果传递btnType的属性值为link并设置disabled属性,按钮就是禁用状态。
  });
  if(btnType === "link" && href){
    return (
      <a
        className={classes}
        href={href}
        {...restProps} //解析按钮与超链接的原生事件属性
      > 
        {children}
      </a>
    )
  }else{
    return(
      <button
          className={classes}
          disabled={disabled}
        	{...restProps}
      >
        {children}
      </button>
    )
  }
}
/*定义 props 的默认值*/
Button.defaultProps = {
  disabled:false,
  btntype:ButtonType.Default,
  btntype:ButtonSize.Large,
}
export default Button;

添加默认样式

npm install --save normalize.css

在src目录先新建styles文件夹,在styles文件夹下新建index.css | index.scss文件

在styles/index.css文件中引入normalize.css & components/Button/buttom.css

在src/index.tsx文件中引入styles/index.css

import React from 'react';
import ReactDOM from 'react-dom/client';
import './styles/index.scss'
import App from './App';
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

在src新建components/Button/buttom.css | buttom.scss组件

.btn { 
 	position: relative;
  display: inline-block;
  font-weight: 400;
  line-height: 1.5;
  white-space: nowrap;
  text-align: center;
  vertical-align: middle;
  background-image: none;
  border: 1px solid transparent;
  border-radius: 0.25rem;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
  cursor: pointer;
}
.btn-danger { 
  color: #fff;
  background: #dc3545;
  border-color: #dc3545;
}
.btn-primary { 
  color: #fff;
  background: #0d6efd;
  border-color: #0d6efd;
}
.btn-lg { 
  padding: 0.5rem 1rem;
  font-size: 1.25rem;
  border-radius: 0.3rem;
}
.btn-sm { 
  padding: 0.25rem 0.5rem;
  font-size: 0.875rem;
  border-radius: 0.2rem;
}
.btn-xxx { 
  width:200px;
  height:200px;
}
.btn-link {
  font-weight: 400;
  color: #0d6efd;
  text-decoration: none;
  box-shadow: none;
}
.disabled,
.btn[disabled]{
  cursor: not-allowed;
  opacity: 0.65;
  box-shadow: none;
}

在scr/App.tsx组件中引入Button组件

import React from 'react';
// 导入Button 组件
import Button,{ButtonType,ButtonSize} from './conponents/Button/button';
/*Button组价可选属性
	组件类型
  	ButtonType.Primary = 'primary'
    ButtonType.Default = 'default'
    ButtonType.Danger = 'danger'
    ButtonType.Link = 'link'
  组件大小
    ButtonSize.Large = 'lg'
    ButtonSize.Small = 'sm'
*/
function App() {
  return (
    <div className="App">
      <Button autoFocus>Hello</Button>
      <Button className='btn-xxx'>Hello</Button>
      <Button disabled>Disabled Button</Button>
      <Button btnType={ButtonType.Primary} size={ButtonSize.Large}>Primary-Lrage-Button</Button>
      <Button btnType={ButtonType.Danger} size={ButtonSize.Small}>Danger-Small-Button</Button>
      <Button btnType={ButtonType.Link} href='http://www.xxx.com' disabled>被禁用的按钮</Button>
      <Button btnType={ButtonType.Link} href='http://www.xxx.com'  target='target'>在新窗口打开</Button>
    </div>
  );
}
export default App;

在当前项目终端组输入npm start启动项目查看结果

以上就是react结合typescript 封装组件实例详解的详细内容,更多关于react typescript 封装组件的资料请关注脚本之家其它相关文章!

相关文章

  • React构建组件的几种方式及区别

    React构建组件的几种方式及区别

    这篇文章主要介绍了React构建组件的几种方式及区别,组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念来实现开发的模式文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • 在React中this容易遇到的问题详解

    在React中this容易遇到的问题详解

    这篇文章主要介绍了在React中this容易遇到的问题总结,文中有详细的示例代码,希望对大家有一定的帮助,需要的朋友可以参考下
    2023-05-05
  • 在create-react-app中使用sass的方法示例

    在create-react-app中使用sass的方法示例

    这篇文章主要介绍了在create-react-app中使用sass的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • 通过示例源码解读React首次渲染流程

    通过示例源码解读React首次渲染流程

    这篇文章主要为大家通过示例源码解读React的首次渲染流程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • React利用scheduler思想实现任务的打断与恢复

    React利用scheduler思想实现任务的打断与恢复

    这篇文章主要为大家详细介绍了React如何利用scheduler思想实现任务的打断与恢复,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下
    2024-03-03
  • 解决React报错Style prop value must be an object

    解决React报错Style prop value must be a

    这篇文章主要为大家介绍了React报错Style prop value must be an object解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • react-redux及redux状态管理工具使用详解

    react-redux及redux状态管理工具使用详解

    Redux是为javascript应用程序提供一个状态管理工具集中的管理react中多个组件的状态redux是专门作状态管理的js库(不是react插件库可以用在其他js框架中例如vue,但是基本用在react中),这篇文章主要介绍了react-redux及redux状态管理工具使用详解,需要的朋友可以参考下
    2023-01-01
  • React 程序设计简单的轻量级自动完成搜索框应用

    React 程序设计简单的轻量级自动完成搜索框应用

    这篇文章主要为大家介绍了React 程序设计简单的轻量级自动完成搜索框应用,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • 详解create-react-app 自定义 eslint 配置

    详解create-react-app 自定义 eslint 配置

    这篇文章主要介绍了详解create-react-app 自定义 eslint 配置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • React中组件复用的方式总结

    React中组件复用的方式总结

    这篇文章主要为大家详细介绍了Mixin、HOC、Render Props、Hooks这四种组件间复用的方式,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-06-06

最新评论