create-react-app

使用 create-react-app 新建一个 typescript 项目

  1. npx create-react-app ts-with-react --typescript
  2. // 常规新建react项目后添加typescript支撑

React.FunctionComponent

react 官方提供的一个类型,用来写 tsx 中的函数组件

  • 自带一个默认的泛型接口 ```typescript interface IHelloProps { message: string }

const HomePage: React.FunctionComponent = (props) => { return (

{props.message}
) }

  1. 可以通过这个接口自己定义传入参数的类型
  2. - 通过这个类型生成的函数组件自带一些静态的属性
  3. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/8360004/1628841204848-fa830b1a-b3ac-4955-94c6-c9ceacc7699c.png#clientId=u07584130-65f5-4&from=paste&height=276&id=uab29692d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=276&originWidth=489&originalType=binary&ratio=1&size=15591&status=done&style=none&taskId=u6c4ccc18-f0f6-4d88-89d8-978991b23d8&width=489)
  4. - 可以简写成类型别名
  5. ```typescript
  6. const HomePage: React.FC<IHelloProps> = (props) => {
  7. return (
  8. <div>
  9. {props.message}
  10. </div>
  11. )
  12. }
  13. export default HomePage

自定义hook

  • 将组件的逻辑提取到可服用的函数中

例子: 抽取一个自定义的Hook,实现鼠标移动获取当前鼠标位置的坐标

  1. import React ,{useState, useEffect} from 'react'
  2. const useMousePosition = () => {
  3. const [position, setPosition] = useState({x: 0, y:0})
  4. useEffect(() => {
  5. const updateMouse = (e: MouseEvent) =>{
  6. setPosition({x: e.clientX, y: e.clientY})
  7. }
  8. document.addEventListener('mousemove', updateMouse)
  9. return () =>{
  10. document.removeEventListener('mousemove', updateMouse)
  11. }
  12. }, [])
  13. return position
  14. }
  15. export default useMousePosition

注意,自定义的 hook 文件名必须以 use 开头,如 useMousePosition.ts

  • 没有 hook 之前,高阶组件(HOC)是怎么做的

高阶组件就是一个函数,该函数接收一个组件为参数,并且返回一个新组件

使用高阶组件的弊端:
需要添加无需要的节点,代码可读性不高

  • 使用自定义 Hook 完成一个加载图片的功能 ```typescript import { useState, useEffect } from “react”; import axios from ‘axios’

const useURLLoader = (url: string, deps: any[] = []) => { const [data, setData] = useState(null) const [isLoading, setLoading] = useState(false)

useEffect(() => { setLoading(true)

  1. axios.get(url).then(res => {
  2. console.log(res, 'res')
  3. setData(res.data)
  4. setLoading(false)
  5. })

}, deps)

return [data, isLoading] } export default useURLLoader

  1. 通过自定义的 hook ,我们可以直接在其他需要实现加载图片的地方使用
  2. ```typescript
  3. const [data, isLoading] = useURLLoader('https://dog.ceo/api/breeds/image/random', [isUpdate])

对于 useState 的理解

state 并没有监听什么数据的变化,每次渲染中都是相对对独立的,我们看到的更新是因为 state 对应的组件进行了重新渲染,并得到了新的state

useContext

对于 useContext 的复习
在 react 的组件中,状态一层一层的往下传递,如果有一个全局的状态需要在很多组件中使用,那么根组件和当前组件之间的所有组件都需要传递这个状态,useContext 就是为了解决这个问题出现的

context 可以共享对于组件来说是一些全局的属性

  • 创建一个控制全局颜色主题的 context ```typescript // 第一步,在根组件中创建 context,定义context 的属性 interface IThemeProps { [key: string]: {color: string, background: string} }

// 主题的类型,以及主题属性 const themes: IThemeProps = { ‘light’: { color: ‘#000’, background: ‘#222’ } } const themes: IThemeProps = { ‘light’: { color: ‘#000’, background: ‘#222’ } }

// 第二步,创建传递属性使用的context,并导出 export const ThemeContext = React.createContext(themes.light)

// 第三步,包裹住需要使用该属性的所有组件的父组件

// 第四步,在需要使用全局属性的地方引用 useContext,并导入创建的context import { ThemeContext } from ‘../../xxx’ const theme = useContext(ThemeContext)

// 测试,可以拿到全局定义的属性 theme ```

hook规则

  • 只允许在最顶层使用 hook
  • 只允许在函数组件中使用 hook

组件库

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

  • 代码结构
  • 样式解决方案
  • 组件的需求分析和编码
  • 组件测试用例分析和编码
  • 代码打包输出和发布

    样式解决方案

  • inline css

行内样式,定义一个样式对象,直接传入组件

  • css in js
  • style components
  • sass/less

构建色彩体系

  • 系统色板 - 基础色板 + 中性色板
  • 产品色板 - 品牌色 + 功能体系

图标ICON的解决方案

  • 雪碧图 css sprite
  • fontIcon
  • svg

Font-awesome