使用React+TypeScript构建自己的组件库

   2023-02-09 学习力0
核心提示:TypeScript基础数据类型ECMAScript标准定义了8种数据类型BooleanNullUndefinedNumberBigIntStringSymbolObjectinterface接口interface的主要作用如下:对对象的形状(shape)进行描述对类(class)进行抽象Duck Typing(鸭子类型)interface Person {readonly id: n

TypeScript基础

数据类型

ECMAScript标准定义了8种数据类型

  1. Boolean
  2. Null
  3. Undefined
  4. Number
  5. BigInt
  6. String
  7. Symbol
  8. Object

interface接口

interface的主要作用如下:

  1. 对对象的形状(shape)进行描述
  2. 对类(class)进行抽象
  3. Duck Typing(鸭子类型)
interface Person {
  readonly id: number;
  name: string;
  age?: number;
}

函数表达式

const add: (x: number, y: number, z: number) => number = function (x, y, z): number {
  return x + y + z;
}

面向对象的三大特性:封装,继承,多态

  • 封装:当我们使用类中的某个方法时,我们无需知道类中的具体实现细节
  • 继承:子类可以继承父类,让子类具有父类的属性以及方法
  • 多态:子类可以覆盖父类中的方法,从而让子类和父类的实例表现出不同的特性
class Animal {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  run() {
    console.log(`${this.name} is running`)
  }
}

class Cat extends Animal {
  constructor(name: string) {
    super(name);
    // 重写父类的构造方法,首先需要使用super调用父类的构造函数
    console.log(this.name);
  }

  run () {
    console.log('miao~');
    // 当在子类中需要调用父类的方法时,也可以使用super来调用
    super.run();
  }
}

类中属性或者方法的访问修饰符

  • private: 仅仅能够在当前类的内部访问,在子类或者实例中都无法访问
  • protected: 可以在当前类内部和子类中访问,无法在实例中访问
  • public: 默认的访问修饰符,能够在类,子类,实例中都可以访问到
  • readonly: 用来修饰类中不可变的属性
  • static: 可以直接用类名来访问其修饰的属性和方法

接口interface

当多个class需要都需要实现某些相同的方法时,我们可以使用interface来实现

interface Radio {
  switchRadio() :void;
}

class Car implements Radio {
  switchRadio() {}
}

class Phone implements Radio {
  switchRadio() {}
}

常量枚举

const enum Direction {
    Up = 'UP',
    Down = 'DOWN',
    Left = 'LEFT',
    Right = 'RIGHT'
}

泛型约束

可以使用extends关键字来对泛型参数进行限制

interface IWithLengh {
  length: number;
}

function echoWithLength<T extends IWithLengh>(arg: T): T {
  console.log(arg.length);
  return arg;
}

const str = echoWithLength('abc');
const obj = echoWithLength({ length: 1 });
const arr = echoWithLength([1, 2])

类也可以使用泛型来约束

class Queue<T> {
  private data: T[] = [];
  push(item: T): void {
    this.data.push(item);
  }
  pop(): T {
    return this.data.pop();
  }
}
const queue = new Queue<number>();
queue.push(1);
console.log(queue.pop().toFixed(2));

const queue2 = new Queue<string>()

接口也可以使用泛型来约束

interface KeyPair<T, U> {
    key: T;
    value: U;
}

使用泛型来约束函数

interface IPlus<T> {
  (a: T, b: T): T;
}
function plus(a: number, b: number): number {
  return a + b;
}
const a: IPlus<number> = plus

类型别名

类型别名多用于联合类型中

type NameResolver = () => string;
type NameOrResolver = string | NameResolver;
function getName(n: NameOrResolver): string {
  if (typeof n === 'string') {
    return n;
  } else {
    return n();
  }
}

类型断言

function getLength(input: string | number): number {
  if ((<string>input).length) {
    return (<string>input).length;
  } else {
    return input.toString().length;
  }
}

React基础

使用脚手架工具搭建项目

首先使用create-react-app搭建项目

npx create-react-app ts-with-react --typescript

简单的函数式组件

interface IHelloProps {
  message: string;
}
const Hello: React.FC<IHelloProps> = (props) => {
  return <h2>{ props.message }</h2>
}
Hello.defaultProps = {
  message: 'Hello World'
}

React Hooks解决的问题

  • 组件很难复用状态逻辑
  • 复杂组件难以理解,尤其是生命周期函数

useState

该hook相当于组件内的状态

const LikeButton: React.FC = () => {
  const [like, setLike] = useState(0)
  const [status, setStatus] = useState(true)
  return (
    <>
    <button onClick={() => { setLike(like + 1)}}>
      {like}
    </button>
    <button onClick={() => { setStatus(!status) }}>
      {String(status)}
    </button>
    </>
  )
}

useEffect

该hook默认会在第一次渲染完成和每次界面更新时执行,相当于class组件中的componentDidMountcomponentDidUpdate

useEffect(() => {
  document.title = `点击了${like}次`
})

使用useEffect的返回值清除副作用

const LikeButton: React.FC = () => {
  const [position, setPosition] = useState({ x: 0, y: 0 })
  useEffect(() => {
    const updatePostion = (e: MouseEvent) => {
      setPosition({
        x: e.clientX,
        y: e.clientY
      })
    }
    document.addEventListener('click', updatePostion)
    return () => {
      // 会在下一次更新界面之后,重新添加此effect之前执行
      document.removeEventListener('click', updatePostion)
    }
  })

  return <p>X: {position.x}, Y: {[position.y]}</p>
}

控制useEffect执行时机,这里需要使用到useEffect的第二个参数。第二个参数是一个数组,可以填入依赖项,当这些依赖项发生变化时,才会去执行useEffect。当第二个参数为空数组,显然这种情况是没有依赖可以变化的,因此这种情况的useEffect仅仅会在组件加载和卸载时执行一次。

useEffect(() => {
  document.title = `点击了${like}次`
}, [like])

自定义hook

自定义hook需要以use开头

const useMousePosition = () => {
  const [position, setPosition] = useState({ x: 0, y: 0 })
  useEffect(() => {
    const updatePostion = (e: MouseEvent) => {
      setPosition({
        x: e.clientX,
        y: e.clientY
      })
    }
    document.addEventListener('click', updatePostion)
    return () => {
      document.removeEventListener('click', updatePostion)
    }
  }, [])
  return position
}

使用一个自定义hook

const position = useMousePosition()

使用自定义hooks封装一个请求公共hooks

import { useState, useEffect } from 'react'
import axios from 'axios'
const useURLLoader = (url: string, deps: any[] = []) => {
  const [data, setData] = useState<any>(null)
  const [loading, setLoading] = useState(false)
  useEffect(() => {
    setLoading(true)
    axios.get(url).then(result => {
      setData(result.data)
      setLoading(false)
    })
  }, deps)
  return data
}
export default useURLLoader

完成组件库

完成一个组件库需要考虑的问题

  • 代码结构
  • 样式解决方案
  • 组件需求分析和编码
  • 组件测试用例分析和编码
  • 代码打包输出和发布
  • CI/CD,文档生成等

CSS解决方案

  • inline css
  • css in js
  • styled component
  • sass/less

未完待续....2020年06月15日19:18:23

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 项目中使用TypeScript的TodoList实例详解
    项目中使用TypeScript的TodoList实例详解
    目录为什么用todolisttodolist的ts化数据到视图实现handleTodoItemreadonly分类交叉类型新增功能联合类型可选属性数据转视图总结为什么用todolist现代的框架教程目前再也不是写个hello world那么简单了,而是需要有一定基础能力能够做到数据绑定、遍历、条件
    03-16
  • React之 hook / class 结合typescript笔记
    React之 hook / class 结合typescript笔记
    使用 create-react-app 开启 TypeScriptCreate React App 是一个官方支持的创建 React 单页应用程序的CLI,它提供了一个零配置的现代构建设置。当你使用 Create React App 来创建一个新的 TypeScript React 工程时,你可以运行 npx create-react-app my-app
    03-08
  • Angular基础(三) TypeScript
    Angular基础(三) TypeScript
       一、模仿Reddita) 运行ng new –ng4angular-reddit创建应用,从随书代码中复制样式文件,新建组件app-root,代码为:界面可以看到了:b) 对于界面输入的数据,获取的方式有点特别,使用了#newlink这样的语法,newlink是一个对象,现在代表就是所在的inp
    03-08
  • electron教程(番外篇二): 使用TypeScript版本的
    electron教程(一): electron的安装和项目的创建electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google JavaScript Style Guide代码规范electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLintelectron
    03-08
  • 使用 ESModule 和 TypeScript 构建 Node.js 环境
    使用 ESModule 和 TypeScript 构建 Node.js 环
    介绍由于我经常使用 React,所以我在前端接触过 Node.js,但我从未接触过后端。正常搭建环境的时候,不能使用import语句,变成了require语句,很不方便。我认为有各种各样的错误,所以如果你能指出它们,我将不胜感激。执行环境macOS 蒙特雷 ver12.5.1MacBook
    03-08
  • [个人发展] 我做了一个可以永远谈论任何事情的女士对话AI(TypeScript,Python)
    [个人发展] 我做了一个可以永远谈论任何事情的
    在个人发展中对话式人工智能服务 Eveki我做了虚构角色1这是一项以人工智能为特色的服务,可以再现并享受自然对话。这一次,作为第一个艾小姐发表了。请先尝试实物。服务概览与人工智能对话基本上只需输入您的信息是。对话是用女士的语言进行的,就像人类一样
    03-08
  • 使用 Node.js (TypeScript) 和 Azure Functions 创建无服务器 REST API,并获得 CosmosDB 更改源作为奖励。
    使用 Node.js (TypeScript) 和 Azure Functions
    介绍在本文中,我们将使用 azure 函数和 ComsmosDB 创建一个无服务器 REST API 应用程序。使用的语言是 Node.js/TypeScript。此外,由于我们使用 CosmosDB 作为数据库,因此我们将使用 Azure 函数触发器接收 Change Feed 事件作为奖励。创建资源创建资源组az
    03-08
  • 安装 TypeScript 并编译成JS
    安装 TypeScript 并编译成JS
    官网: https://github.com/microsoft/TypeScriptTypeScript是一种由微软开发的开源、跨平台的编程语言。它是JavaScript的超集,最终会被编译为JavaScript代码。TypeScript是一种应用级JavaScript语言。TypeScript为JavaScript添加了可选类型,支持针对任何浏
    03-08
  • 使用TypeScript,AngularJs和Web API构建基本的C
    原文地址:using typescript with angularjs and web api 版权归其作者所有.在这篇文章中我将向大家展示如何使用TypeScript,Angular Js 和Asp.net Web API 来构建一个基本的实现CRUD功能的Web应用程序. Typescript提供了一系列的功能来方便程序员构造和组织更
    02-10
  • Typescript 中类的继承
    Typescript中类的定义与继承与后端开发语言java/C#等非常像,实现起来非常方便,而且代码便于阅读。用Typescript写较大项目时是非常有优势的。/** * BaseClass */class BaseClass {constructor(name:string,age:number) {this.name=name;this.age=age;}name:s
    02-09
点击排行