React + ts学习笔记

news2024/10/7 18:22:14

前提准备:

环境配置

安装node.js

官网安装:当前使用版本18.15.0

安装新的react应用:

运行命令新建react-app

npx create-react-app study-ts-app

当前版本:

  • “react”: “^18.2.0”,
  • “react-dom”: “^18.2.0”,
    如果出现如下问题,无法安装依赖
    image.png
    可以尝试运行npm i react,如果报错,执行推荐命令
    image.png
    运行命令:
sudo chown -R 502:20 "/Users/rcdl/.npm"

命令详解参考:https://blog.csdn.net/wangcheeng/article/details/128165359
然后继续执行create-react-app

安装typeScript

npm i typescript --save
  • “typescript”: “^5.0.4”,

在react中使用ts

参考:https://juejin.cn/post/7021674818621669389

在类组件

参数没有都可以被省略

// 使用方式:React.Component<P, S={}>{...}

// 示例:
import * as React from 'react'
interface IProps {
  name: string;
}

interface IState {
  age: number;
}

class Hello extends React.Component<IProps, IState> {
  state = {
    age: 18
  };

  render() {
    return (
      <div>
        {this.state.age}
        {this.props.name}
      </div>
    );
  }
}

export default Hello;

React.Component中P是props类型的定义,S是state类型的定义,都是泛型接口

React.PureComponent<P, S={} SS={}>{...}

React.PureComponent前两个值含义相同,第三个值代表getSnapshotBeforeUpdate的返回值

在函数组件

在函数组件中,也可以接收一个参数(可省),参数表示props的类型,示例如下

interface IProps {
  name: string
}

const HelloFunction = (props: IProps) => {
  const {name} = props;

  return (
    <div className="App">
      <h1>hello world</h1>
      <h2>{name}</h2>
    </div>
  );
}

export default HelloFunction;

定义函数组件的第二种方式,React.FunctionComponent<P={}>来定义,也可以使用其简写React.FC<P={}>,参数可省,示例如下

interface IProps {
  name: string
}

const App: React.FC<IProps> = (props) => {
  const {name} = props;
  return (
    <div className="App">
      <h1>hello world</h1>
      <h2>{name}</h2>
    </div>
  );
}

export default App;

当使用这种形式来定义函数组件时,props中默认会带有children属性,它表示该组件在调用时,其内部的元素,来看一个例子,首先定义一个parent组件,组件中引入了Child1和Child2组件:

import Child1 from "../childFunction/child1";
import Child2 from "../childFunction/child2";

interface IProps {
  name: string;
}
const Parent: React.FC<IProps> = (props) => {
  const { name } = props;
  return (
    <Child1 name={name}>
      <Child2 name={name} />
      my test content
    </Child1>
  );
};

export default Parent;

child1组件如下

interface IProps {
  name: string;
}
const Child1: React.FC<React.PropsWithChildren<IProps>> = (props) => {
  const { name, children } = props;
  console.log(children);
  return (
    <div className="App">
      <h1>hello child1</h1>
      <h2>{name}</h2>
    </div>
  );
};

export default Child1;

这里的props.children是默认属性,输出结果是children的内容,就是parent组件中child1包裹起来的child2对象和文字
image.png

useState

如定义一个数字类型,有初始值可以直接写

const [flag, setFlag] = useState<number>(1)

没有初始值或初始值为null可以写成:

const [flag, setFlag] = useState<number | null>()

如初始化是一个对象
在确定对象中的属性类型和数量时,可以使用泛型定义

interface list {
    title: string,
    type: boolean
  }
  const [list, setList] = useState<list>({ title: '', type: false })
  setList({ title: '', type: true })

在未知对象属性数量和类型时
???

其他类型见下方扩展:ts基本类型

useRef

react写法

const frameRef = useRef(null);

ts写法

// 改变值时类型null不加也没显示报错--存疑?
const frameRef = useRef<HTMLInputElement | null>(null)

实例:

  const myText = useRef<HTMLInputElement | null>(null);
  console.log(myText.current) // null
  const changeText = (e) => {
  // myText的值会随着input中内容的输入实时改变
    myText.current.innerHTML = e.target.value;
  }

  return (
    <div>
      <input type="text" onChange={(e) => changeText(e)} />
      <h2 ref={myText} />
    </div>
  );

useMemo

useMemo返回的是一个值,所以需要有返回类型,如果返回类型和定义类型不同会报错

注:useCallback不需要定义返回值类型,因为他返回的是一个函数

const calculatedValue1 = useMemo<number>(() => a ** 2, [a]);

事件处理

常见的Event事件对象如下:

  • 剪切板事件对象:ClipboardEvent<T = Element>
  • 拖拽事件对象:DragEvent<T = Element>
  • 焦点事件对象:FocusEvent<T = Element>
  • 表单事件对象:FormEvent<T = Element>
  • Change事件对象:ChangeEvent<T = Element>
  • 键盘事件对象:KeyboardEvent<T = Element>
  • 鼠标事件对象:MouseEvent<T = Element, E = NativeMouseEvent>
  • 触摸事件对象:TouchEvent<T = Element>
  • 滚轮事件对象:WheelEvent<T = Element>
  • 动画事件对象:AnimationEvent<T = Element>
  • 过渡事件对象:TransitionEvent<T = Element>

例如:
MouseEvent是上面的鼠标事件对象(click事件)HTMLDivElement代表该函数作用于一个div元素

const handleChangeCurrent = (e: React.MouseEvent<HTMLDivElement>) => {}

事件处理函数的类型声明

type EventHandler<E extends SyntheticEvent<any>> = { bivarianceHack(event: E): void }["bivarianceHack"];

type ReactEventHandler<T = Element> = EventHandler<SyntheticEvent<T>>;
// 剪切板事件处理函数
type ClipboardEventHandler<T = Element> = EventHandler<ClipboardEvent<T>>;
// 复合事件处理函数
type CompositionEventHandler<T = Element> = EventHandler<CompositionEvent<T>>;
// 拖拽事件处理函数
type DragEventHandler<T = Element> = EventHandler<DragEvent<T>>;
// 焦点事件处理函数
type FocusEventHandler<T = Element> = EventHandler<FocusEvent<T>>;
// 表单事件处理函数
type FormEventHandler<T = Element> = EventHandler<FormEvent<T>>;
// Change事件处理函数
type ChangeEventHandler<T = Element> = EventHandler<ChangeEvent<T>>;
// 键盘事件处理函数
type KeyboardEventHandler<T = Element> = EventHandler<KeyboardEvent<T>>;
// 鼠标事件处理函数
type MouseEventHandler<T = Element> = EventHandler<MouseEvent<T>>;
// 触屏事件处理函数
type TouchEventHandler<T = Element> = EventHandler<TouchEvent<T>>;
// 指针事件处理函数
type PointerEventHandler<T = Element> = EventHandler<PointerEvent<T>>;
// 界面事件处理函数
type UIEventHandler<T = Element> = EventHandler<UIEvent<T>>;
// 滚轮事件处理函数
type WheelEventHandler<T = Element> = EventHandler<WheelEvent<T>>;
// 动画事件处理函数
type AnimationEventHandler<T = Element> = EventHandler<AnimationEvent<T>>;
// 过渡事件处理函数
type TransitionEventHandler<T = Element> = EventHandler<TransitionEvent<T>>;**

扩展:ts基本类型

布尔值true/false:boolean

let isDone: boolean = false;

数字:number

ts支持二进制、八进制、十进制和十六进制字面量。

let age: number = 6; 

字符串:string

let name: string = 'jack';

null和undefined

let u: undefined = undefined;
let n: null = null;

Symbol

Symbol是不可改变且唯一的。

let sym: symbol = Symbol()

数组:[]

定义数组的两种方式:

1 在元素类型后接上 []

2 使用数组泛型,Array<元素类型>

let list: number[] = [1, 2, 3];          //定义各项都是数字的数组。
let list: Array<number> = [1, 2, 3];     
let list: string[] = ['1', '2', '3'];          //定义各项都是字符串的数组。
let list: Array<string> = ['1', '2', '3'];    

元组 Tuple

元组类型可以定义已知元素数量和各元素类型的数组。

当访问已知索引的元素,会得到正确的类型;当访问越界的元素,会使用联合类型代替。

let data: [string, number];
data = ['jack', 20];

枚举:enum

枚举类型可以为一组数值赋予名字。默认情况下,元素从0开始编号,也可以手动指定元素的值。

enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;

枚举类型还可以根据枚举的值得到他的名字。

enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];
console.log(colorName);  // Green

Any

any用于在不确定变量类型时使用。比如用户输入或第三方代码库引用,或者定义不同类型元素的数组。

ts默认这些值是不需要类型检查直接编译。

let notSure: any = 4;
notSure = "a string";
let list: any[] = [1, true, "jack"];

Unknown

与any类似,但是会做类型检查再编译。

function divide(param: unknown) {
  // return param / 2;  // 不知道params的类型使用了运算符会编译错误
  return param as number / 2;
}

Void

void表示没有任何类型。void类型只能赋值为null或undefined。

当一个函数没有返回值或者返回值是undefined时,他的返回值类型可以用void。

function warnUser(): void {
  console.log("This is my warning message");
}

Never

never类型表示永不存在的值的类型;如:

1 函数执行时抛出异常

2 函数中的代码无限循环,到不了返回值那一步

never是任何类型的子类型,可以赋值给任何类型。

// 异常
function fn(msg: string): never { 
  throw new Error(msg)
}

// 死循环
function fn(): never { 
  while (true) {}
}

Object

定义object对象类型的方式:

1 直接定义类型为object

2 将对象内属性的类型都逐个定义

let obj: object = { name: 'lin', age: 18 };
let person: { 
  age: number, name: string 
} = { age: 12, name: 'jack' };

类型扩展

类型断言

当绝对确认一个实体的类型时使用,使用方式有两种;

1.实体 as 类型(支持JSX)

2.<类型>实体

let someValue: any = "this is a string";
let strLength1: number = (someValue as string).length;
or
let strLength2: number = (<string>someValue).length;

类型别名

当定义的类型名过长或复杂时可以定义个别名,方便书写。

type s = string | number;
const str: s = 'jack';

也可以写成对象形式,定义具体的变量类型

type A = { name: string }

其他常用类型

联合类型

联合类型是由两个及以上种类型组成的类型,表示变量可以是其中的任意一种类型;且只能访问他们共有的方法和属性。

let timer: number | string | null = 1;

内置类型

ECMAScript的内置对象

const nums: Array<number> = [1,2,3]
const date: Date = new Date()
const err: Error = new Error('Error!');
const reg: RegExp = /abc/;

字面量类型

用type定义成一个字面量然后使用,能够减少代码量,降低耦合性。

type ButtonSize = 'mini' | 'small' | 'normal' | 'large'
const btnSize: ButtonSize = 'small'

函数

创建

ts可以创建有名字的函数和匿名函数。

function add(x: number, y: number): number {
  return x + y;
}

let myAdd = function (x: number, y: number): number {
  return x + y;
};

let myAdd1: (x: number, y: number) => number =
  function (x: number, y: number): number {
    return x + y;
  };

传参

已知参数个数

传递给一个函数的参数个数必须与函数期望的参数个数一致,不一致会报错。

function buildName(firstName: string, lastName: string) {
  return firstName + " " + lastName;
}
let result1 = buildName("Bob"); // error
let result3 = buildName("Bob", "Adams");        

如果参数可传可不传,可以在参数名后加 ? ,实现参数可选功能,没传默认是undefined。

可选参数必须放在必须参数后面。

function buildName(firstName: string, lastName?: string) {
  if (lastName)
    return firstName + " " + lastName;
  else
    return firstName;
}
let result1 = buildName("Bob");                  
let result2 = buildName("Bob", "Adams", "Sr."); // error, 应有 0-2 个参数,但获得 3 个。
let result3 = buildName("Bob", "Adams");         

如果是带默认值的参数放在必须参数前,要求必须明确的传入undefined值获得默认值。

function buildName(firstName = "Will", lastName: string) {
    return firstName + " " + lastName;
}
let result4 = buildName(undefined, "Adams");

未知参数个数

如果传参个数不确定,可以把所有参数收集到一个变量中。

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

泛型

泛型的关键目的是给成员之间提供有意义的约束。成员可以是:

1 类的实例成员

2 类的方法

3 函数参数

4 函数返回值

使用泛型可以创建可重用的通用组件,一个组件可以支持多种类型的数据,在定义的时候不预先指定具体的类型,而是在使用的时候再指定。不同于any,他不会丢失信息,传入和返回类型相同。

定义泛型函数

给函数添加类型变量T(type),可以捕获到用户传入的类型;并使用T作为返回值类型。

其他常见泛型变量:

1 K(Key):表示对象中的键类型;

2 V(Value):表示对象中的值类型;

3 E(Element):表示元素类型。

function identity<T>(arg: T): T {
    return arg;
}

使用泛型函数

使用泛型函数的方法有两种

1 传入所有参数和参数类型

2 传入参数,不传类型,编译器会根据传入的参数自动确定T的类型

let output = identity<string>("myString"); 
let output = identity("myString"); 

泛型接口

interface GenericIdentityFn {
  <T>(arg: T): T;
}

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: GenericIdentityFn = identity;

返回两种类型的对象

// 创建一个Identities 接口
interface Identities<V, M> {
  value: V,
  message: M
}
// 将 Identities 接口作为 identity 函数的返回类型
function identity<T, U> (value: T, message: U): Identities<T, U> {
  console.log(value + ": " + typeof (value));
  console.log(message + ": " + typeof (message));
  let identities: Identities<T, U> = {
    value,
    message
  };
  return identities;
}

console.log(identity(68, "Semlinker"));
// 68: number
// Semlinker: string
// {value: 68, message: "Semlinker"}

泛型类

泛型类与泛型接口类似。 泛型类使用(<T, …>)括起泛型类型,定义多个类型变量,跟在类名后面。

class GenericNumber<T> {
  zeroValue: T;
  add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

泛型约束

用于限制每个类型变量接受的类型数量。

如要求类型变量上对应的类型存在某些属性(length,push),在没有明确T类型时是不能使用length属性的。

function identity<T>(arg: T): T {
  console.log(arg.length); // Error
  return arg;
}

可以让类型变量extends一个含有所需属性(length)的接口(Length),可以获取到length属性。

但是如果调用identiy时传入参数不带有length属性会报错。

interface Length {
  length: number;
}
// 也可以使用多种约束类型
// <T extends Length, Type2, Type3, ...>
function identity<T extends Length>(arg: T): T {
  console.log(arg.length); // 可以获取length属性
  return arg;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/495910.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

优维低代码实践:第一个微应用

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…

vue-element-admin踩坑合集+完整包(项目源码 +依赖)

目录 Nodejs版本&#xff1a; 安装依赖时遇到的报错&#xff1a; 启动报错&#xff1a; vue-element-admin完整包地址&#xff1a; 在部署安装使用vue-element-admin开源项目的时候&#xff0c;会遇到各种各样的问题。 这里是本人遇到的一些坑。。。。。。 Nodejs版本&am…

【技术碎片】【Java】计算椭圆的外接矩形坐标

目录 前言原生实现&#xff08;错误方法&#xff09;精确实现&#xff08;数学解&#xff09;参考 前言 遇到一个需要计算一般椭圆&#xff08;斜椭圆&#xff09;的外接矩形坐标的问题&#xff0c;在此记录一下 已知椭圆的中心点坐标centerX centerY&#xff0c;椭圆的长轴&…

FPGA - 7系列 FPGA内部结构之CLB -02- CLB功能详解

前言 本文翻译自UG474第二章&#xff0c;主要对7系列FPGAs CLB结构进行详细介绍。这些细节对设计优化和验证很有帮助。 CLB 排列 CLB 在 7 系列 FPGA 中按列排列。 7 系列是基于 ASMBL架构提供的独特柱状方法的第四代产品。ASMBL 架构 Xilinx 创建了高级硅模块块 (ASMBL) 架…

【hello Linux】线程互斥

目录 1. 互斥量mutex 2. 互斥量的接口 2.1 初始化互斥量 2.2 销毁互斥量 2.3 互斥量加锁和解锁 2.4 互斥量实现原理探究 3. 可重入VS线程安全 4. 常见锁概念 5. 多线程抢票系统 Linux&#x1f337; 在介绍线程互斥前&#xff0c;我们先来看几个专业性术语&#xff1a; 【临界资…

边缘计算节点是啥?边缘计算与CDN有什么关系?一文带你了解边缘计算节点BEC

边缘计算节点是基于CDN边缘节点构建&#xff0c;覆盖全国大部分地区&#xff0c;三大运营商全覆盖。将算力下沉到各城市级节点&#xff0c;提供离用户更近的算力资源。 那么可能有些小伙伴会问&#xff0c;CDN也是就近为用户提供服务&#xff0c;边缘计算节点和CDN有什么不同呢…

时序数据利用EEMD_LSTM模型进行预测(Python编程,数据集和代码均在压缩包,解压缩后可以直接运行,数据可以替换为股票数据,交通流量等时序数据)

运行效果(为减少录屏时间&#xff0c;视频中epoch设置为30&#xff0c;改为100效果更佳):利用EEMD_LSTM模型对时序数据进行预测&#xff08;视频中epoch为30&#xff0c;当为100 的时候效果更佳&#xff09;_哔哩哔哩_bilibili 1.数据介绍&#xff1a;以每天为间隔的时序数据 …

达梦:dts工具迁移mysql decimal(65,30)的字段,报精度超出定义

本文旨在分享迁移MySQL decimal字段​​​​​​​时遇到“精度超出定义”问题时&#xff0c;如何理解MySQL和达梦对于decimal 等这一类数值数据类型。 1.了解达梦的数值数据类型定义 ​​​​​​​​​​​​​​NUMERIC 类型 语法&#xff1a;NUMERIC[(精度 [, 标度])]功…

HBase基础

HBase基础 一、初识HBase HBase 是一个面向列式存储的分布式数据库&#xff0c;其设计思想来源于 Google 的 BigTable 论文。HBase 底层存储基于 HDFS 实现&#xff0c;集群的管理基于 ZooKeeper 实现。HBase 良好的分布式架构设计为海量数据的快速存储、随机访问提供了可能&…

实验二 存储器管理

实验二 存储器管理 实验目的&#xff1a; 理解各类置换算法的原理和虚拟存储器管理的方法。 实验内容&#xff1a; 编程实现LRU算法或CLOCK/改进算法等置换算法&#xff08;二选一&#xff09;&#xff0c;模拟实现虚拟存储器的地址变换过程。 实验步骤&#xff1a; 1…

C++之虚函数原理

对象数据和函数的存储方式 注意说的是对象。 C中的对象存储方式是 每个对象占用的存储空间只是该对象的数据部分&#xff08;虚函数指针和虚基类指针也属于数据部分&#xff09;&#xff0c;函数属于公共部分。 虚函数表 虚函数是通过虚函数表实现的。 C实现虚函数的方法是…

open3d io操作

目录 1. read_image, write_image 2. read_point_cloud, write_point_cloud 3. 深度相机IO操作 4. Mesh文件读取 1. read_image, write_image 读取jpg. png. bmp等文件 image_io.py import open3d as o3dif __name__ "__main__":img_data o3d.data.JuneauIma…

Redis持久化---RDBAOF

目录 一、什么是持久化&#xff0c;为什么要持久化&#xff1f; 二、RDB 2.1 配置文件 2.2 自动触发 2.3 手动触发 2.4 RDB优缺点 2.5 如何修复dump.rdb文件 2.6 哪些情况会触发快照 && 如何禁用RDB&#xff1f; 三、AOF 3.1 什么是AOF&#xff1f; 3.2 AO…

(四)Kubernetes - 手动部署(二进制方式安装)

Kubernetes - 手动部署 [ 3 ] 1 部署work node1.1 创建工作目录并拷贝二进制文件1.2 部署kubelet1.2.1 创建配置文件1.2.2 配置文件1.2.3 生成kubelet初次加入集群引导kubeconfig文件1.2.4 systemd管理kubelet1.2.5 启动并设置开机启动1.2.6 允许kubelet证书申请并加入集群 1.3…

猫狗训练集训练报错:Failed to find data adapter that can handle input

这里写自定义目录标题 Jupyter Notebook6.5.4 tensorflow 2.12.0 pillow 9.5.0 numpy 1.23.5 keras 2.12.0 报错详细内容&#xff1a; ValueError: Failed to find data adapter that can handle input: (<class ‘tuple’> containing values of types {“<class ‘k…

Midjourney关键词分享!附输出AI绘画参考图

Midjourney 关键词是指用于 Midjourney 这个 AI 绘画工具的文本提示&#xff0c;可以影响生成图像的风格、内容、细节等。Midjourney 关键词有一些基本的语法规则和套用公式&#xff0c;也有一些常用的风格词汇和描述词汇&#xff0c;这里我以10张不同风格和类型的美女图为例&a…

windows 下Node.js 版本管理工具

目录 1、概述&#xff1a; 2、下载安装 3、nvm命令 4、如何安装不在可用列表里面的版本 1、概述&#xff1a; 不同项目使用的nodejs版本和依赖等不同&#xff0c;需要进行nodejs的版本切换&#xff0c;使用nvm可以方便的切换当前的nodejs版本 windows可以使用 nvm-window…

AP360X 可充电多功能LED手电筒与移动照明控制ic和应用方案

产品展示 线路图如下&#xff1a; ​ AP360X芯片应用原理图和扩容1.8A应用&#xff1a; ​​ 1&#xff0c;产品介绍 AP360X 系列产品是一款多种模式可选 的单芯片 LED 手电筒控制芯片&#xff0c;集成了锂电 池充电管理模块、手电筒功能控制模块和保 护模块&#xff0c;关机…

剑指 Offer 34. 二叉树中和为某一值的路径 / LeetCode 113. 路径总和 II(深度优先搜索)

题目&#xff1a; 链接&#xff1a;剑指 Offer 34. 二叉树中和为某一值的路径&#xff1b;LeetCode 113. 路径总和 II 难度&#xff1a;中等 给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 …

身为程序员,你有哪些提高写代码效率的黑科技?

目录 1、Google/Stackoverflow——搜索解决方案的能力 2、低代码平台——提供可复用的轮子 3、人工智能——帮你写代码 4、学会话术——消除烦恼 5、 按时上下班&#xff0c;一周工作 5 天&#xff0c;养足精神以更高效地写代码。 首先&#xff0c;每个程序员都是会利用工…