TypeScript基础
1.数据类型
ECMAScript标准定义了8种数据类型
1.Boolean
2.Null
3.Undefined
4.Number
5.BigInt
6.String
7.Symbol
8.Object
2.interface接口
interface的主要作用如下:
1.对对象的形状(shape)进行描述
2.对类(class)进行抽象
3.Duck Typing(鸭子类型)
interface Person {
  readonly id: number;
  name: string;
  age?: number;
}3.函数表达式
const add: (x: number, y: number, z: number) => number = function (x, y, z): number {
  return x + y + z;
}4.类
面向对象的三大特性:封装,继承,多态
- 封装:当我们使用类中的某个方法时,我们无需知道类中的具体实现细节
 - 继承:子类可以继承父类,让子类具有父类的属性以及方法
 - 多态:子类可以覆盖父类中的方法,从而让子类和父类的实例表现出不同的特性
 
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: 可以直接用类名来访问其修饰的属性和方法
 
5.接口interface
当多个class需要都需要实现某些相同的方法时,我们可以使用interface来实现
interface Radio {
  switchRadio() :void;
}
class Car implements Radio {
  switchRadio() {}
}
class Phone implements Radio {
  switchRadio() {}
}6.常量枚举
const enum Direction {
    Up = 'UP',
    Down = 'DOWN',
    Left = 'LEFT',
    Right = 'RIGHT'
}7.泛型约束
可以使用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> = plus8.类型别名
类型别名多用于联合类型中
type NameResolver = () => string;
type NameOrResolver = string | NameResolver;
function getName(n: NameOrResolver): string {
  if (typeof n === 'string') {
    return n;
  } else {
    return n();
  }
}9.类型断言
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 Hocks 解决问题
- 组件很难复用状态逻辑
 - 复杂组件难以理解,尤其是生命周期函数
 
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组件中的componentDidMount和componentDidUpdate
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])自定义Hock
自定义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
 
未完待续...

Comments