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

下面是 “react结合typescript 封装组件实例详解”的完整攻略。

一、为什么要使用TypeScript

TypeScript 是 JavaScript 的一个超集,它可以为 JavaScript 提供类型检查和其他一些新特性。TypeScript 具有以下优点:

  • 代码更加健壮,更容易维护。
  • 更好的智能提示和 IDE 支持。
  • 更容易对代码进行重构。
  • 更好的语言规范约束,可以防止出现一些常见的错误。
  • 易于与其他类型需要 TypeScript 支持的框架交互。

二、React 和 TypeScript 结合使用

为了可以更好的使用 React TypeScript,我们需要安装依赖包。

npm install react react-dom @types/react @types/react-dom typescript --save-dev

以上命令会安装 React 和 TypeScript 以及必要的类型定义文件。

接下来,在你的项目中创建一个 src 文件夹,并且创建一个 App.tsx 文件。在这个文件中,我们可以使用 TypeScript 和 React 构建我们的组件。以下是一个简单的例子:

import * as React from 'react';

interface Props {
    name: string;
}

const App: React.FC<Props> = ({ name }) => {
    return (
        <div>
            <h1>Hello, {name}!</h1>
        </div>
    );
};

export default App;

在上面的代码中,我们定义了一个 Props 的接口,它规定了组件需要传入一个名为 name 的属性。然后,我们使用 React.FC 类型定义了一个函数组件,名称为 App,它接受一个 Props 参数,并返回一个 JSX 元素。

三、如何封装 TypeScript 组件

较为常见的做法是,把类组件和函数式组件的特定结构合并在一起,这有助于保证每个组件都具有一致的 API。

这里我们以类组件的封装为例,将完成一个带计时器的数字输入框扩展按钮组件。

  • 定义属性类型 Props
interface Props {
  /** 输入框值 */
  value?: string;
  /** 输入框value的变化回调 */
  onChange?: (val: string) => void;
  /** 输入框通用属性 */
  [key: string]: any;
  /** 自动计时时长,单位毫秒 */
  autoCountDuration?: number;
}

以上属性中 autoCountDuration 是可选属性,其他以及通用属性皆为必填。

  • 定义组件状态 State
interface State {
  count: number;
}
  • 类组件实现
class InputBox extends React.Component<Props, State> {
  /** 计时器 */
  private timer?: NodeJS.Timeout;
  /** 计数器 */
  private count = 0;

  constructor(props: Readonly<Props>) {
    super(props);
    this.state = {
      count: 0,
    };
  }

  componentDidUpdate(
    prevProps: Readonly<Props>,
    prevState: Readonly<State>
  ) {
    const { autoCountDuration } = prevProps;
    if (this.props.autoCountDuration !== autoCountDuration) {
      // 清除旧时器
      clearTimeout(this.timer!);
      if (typeof this.props.autoCountDuration === 'number') {
        this.startIntervalCount();
      }
    }
  }

  /**
   * 自动计时数数,使用类模式
   */
  private startIntervalCount() {
    this.count = 0;
    this.timer = setInterval(() => {
      this.count += 1;
      this.setState({ count: this.count });
    }, this.props.autoCountDuration!);
  }

  /**
   * 值变化事件
   *
   * @param e
   */
  private onChange(e: React.ChangeEvent<HTMLInputElement>) {
    const { onChange } = this.props;
    if (onChange) {
      onChange(e.target.value);
    }
  }

  /** 点击按钮 */
  private onBtnClick() {
    alert('你点击了扩展按钮!');
  }

  render() {
    const { count } = this.state;
    const { value, ...rest } = this.props;
    const btnStyle: React.CSSProperties = {
      marginLeft: '8px',
    };
    return (
      <div>
        <input
          {...rest}
          value={value || ''}
          onChange={this.onChange.bind(this)}
        />
        <button style={btnStyle} onClick={this.onBtnClick.bind(this)}>
          操作
        </button>
        <span>自动计数:</span>
        <span>{count}</span>
      </div>
    );
  }
}

上述代码中,我们首先声明了一个 class 类组件的名称和一个泛型接口 Props,它是一个对象,它用于存储类组件的属性。接着,在定义组件内部状态的声明。

在组件的构造函数中,我们用 super(props) 调用 React.Component 的构造函数,并使用 componentWillMount 设置本地 state。由于 constructor 仅能使用 super 和 state,所以它不适合进行本地状态初始化,因此我们采用 componentWillMount 进行设置。

这里我们需要注意的是,在 componentWillUnmount 函数中一定要记得清除 this.timer,以免造成内存泄露。

四、示例

下面我们来看一个示例:实现一个 TodoList 组件,包括添加和删除条目的功能。

import React, { useState } from 'react';

export type TodoItemType = {
  id: string;
  text: string;
}

interface Props {
  initData?: TodoItemType[];
}

const TodoList: React.FC<Props> = ({ initData = [] }) => {
  const [todoList, setTodoList] = useState<TodoItemType[]>(initData);
  const [textInputVal, setTextInputVal] = useState('');

  const handleTextInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    const val = e.target.value;
    setTextInputVal(val);
  };

  const handleAddTodoItem = () => {
    setTodoList((preList) => [
      ...preList,
      {
        id: String(Date.now() + Math.random() * 1000),
        text: textInputVal,
      },
    ]);
    setTextInputVal('');
  };

  const handleDeleteTodoItem = (id: string) => {
    setTodoList((preList) => preList.filter((item) => item.id !== id));
  };

  return (
    <div>
      <h2>TodoList</h2>
      <div>
        <input value={textInputVal} onChange={handleTextInput} />
        <button onClick={handleAddTodoItem}>添加</button>
      </div>
      <ul>
        {todoList.map((item) => (
          <li key={item.id}>
            <span>{item.text}</span>
            <button onClick={() => handleDeleteTodoItem(item.id)}>删除</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

上述代码中,我们首先定义了一个 TodoItemType 类型,它描述了一个待办事项的结构。接着,我们定义了一个 Props 接口,它规定了组件需要传入一个名为 initData 的属性,它是一个 TodoItemType 数组类型,作为组件初始化的列表数据。

在组件中,我们使用 useState Hook 定义了 todoListtextInputVal 状态。然后,我们将 textInputVal 绑定到 <input> 元素,这样我们就能够实时得到用户输入的文本信息。

在添加函数 handleAddTodoItem 中,我们使用 setTodoList 进行列表的更新。通过展开运算符将前面的列表数据和新增数据合并为一个新的数组并更新到状态中。

最后,我们使用了 map 函数,渲染出列表中的各个项。每一项都会有一个删除按钮,点击时会触发 handleDeleteTodoItem,将待删除的项从待办事项列表中移除。

五、总结

本文介绍了如何利用 TypeScript 封装 React 组件。在这个例子中,我们定义了一个 <InputBox> 组件,并为其添加了计时器和扩展按钮功能,以及一个 <TodoList> 组件,它实现了添加和删除待办事项的功能。在这个过程中,我们学习了如何使用 TypeScript 定义组件 Props 和 State,以及如何在组件中使用 Hook 状态管理数据。最后,我们展示了如何使用 TypeScript 编写 React 组件的注意事项和核心代码。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:react结合typescript 封装组件实例详解 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • JavaScript如何实现跨域请求

    JavaScript 如何实现跨域请求 在前端开发中,常常遇到需要请求不同域名下的 API 接口的情况,此时我们就需要了解 JavaScript 如何实现跨域请求。 在同源策略限制下,JavaScript 无法直接向不同域名进行请求数据,因此需要通过一些技术手段来实现跨域请求,以下是几种通用的实现方式。 JSONP(JSON with Padding) JS…

    JavaScript 2023年6月11日
    00
  • js实现简单的购物车有图有代码

    让我来为大家详细讲解一下如何用js实现简单的购物车吧。 1. 确定数据结构 在开始实现购物车之前,我们需要先确定其数据结构。在此,我们可以采用一个数组来储存购物车中的商品信息,其中每个元素都是一个对象,包含商品的相关信息:名称、价格、数量等,示例代码如下: let cart = [ { name: "商品1", price: 10, qu…

    JavaScript 2023年6月11日
    00
  • Flash & Ajax 操作 XML 实例:无刷新分页

    Flash & Ajax 操作 XML 实例:无刷新分页 介绍 Flash和Ajax都支持与服务器进行异步数据交换,做网站时常常会用到无刷新分页这个功能。本文将介绍在Flash和Ajax协作下实现无刷新分页的完整攻略。 步骤 1. 创建XML文件 首先创建一份XML文件,用于存储需要分页显示的数据。例如: <pages> <page…

    JavaScript 2023年6月11日
    00
  • javascript实现点击单选按钮链接转向对应网址的方法

    这里为您讲解一下“javascript实现点击单选按钮链接转向对应网址的方法”的攻略: 1. HTML 结构 首先,需要在 HTML 中添加单选按钮和链接的结构,例如: <input type="radio" name="link" value="https://www.example.com/1&qu…

    JavaScript 2023年6月11日
    00
  • MySQL pt-slave-restart工具的使用简介

    当MySQL复制出现异常时(如主从延迟、主从不同步),我们可以使用Percona Toolkit中的pt-slave-restart工具来帮助我们快速地解决问题。本篇攻略将详细讲解如何使用pt-slave-restart工具。 什么是pt-slave-restart工具 pt-slave-restart工具是Percona Toolkit中的一款工具,用于重…

    JavaScript 2023年5月28日
    00
  • element UI中在 el-select 与 el-tree 结合组件实现过程

    如果想要在Element UI中通过一个下拉菜单选择树节点,在代码中的实现过程中,我们需要将el-tree组件的节点数据绑定在el-select组件中。下面是实现过程的详细攻略: 1. 被选择节点的数据获取 我们先给el-tree添加ref属性,这样我们在javascript中可以通过$refs属性访问到el-tree组件的实例对象,进而获取到我们选择的节点…

    JavaScript 2023年6月10日
    00
  • Java技术长久占居主要地位的12个原因

    这里我将采用Markdown语法来详细讲解“Java技术长久占居主要地位的12个原因”的完整攻略,具体如下: Java技术长久占居主要地位的12个原因 1. 面向对象编程 Java语言是一门完全基于面向对象编程的语言,因此在处理复杂业务场景时非常得心应手。Java语言的面向对象编程思想使得程序的代码结构、代码维护、开发效率更高,而且在软件开发方面相比其他语言…

    JavaScript 2023年5月28日
    00
  • Javascript中的prototype与继承

    JavaScript的原型(prototype)是一种机制,它允许对象继承另一个对象的属性和方法。在这种机制下,对象可以通过其原型链访问到其他对象的属性和方法。在本篇文章中,我们将探讨 JavaScript 中的 prototype 和继承。 原型(prototype) 每个Javascript对象(除了null和undefined)都有一个内部的属性[[P…

    JavaScript 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部