• TypeScript && React


    环境搭建

    我们当然可以先用脚手架搭建React项目,然后手动配置成支持TypeScript的环境,虽然比较麻烦,但可以让你更清楚整个过程。这里比较麻烦,就不演示了,直接用命令配置好。

    npx create-react-app appname --typescript

    可以安装一些自己需要的库及其声明文件,例如react-router-dom、axios、ant Design等。如果要安装ant design,还需要在开发环境库中安装一些依赖库,以帮助实现按需加载。

    使用

    有类型约束的函数组件

    import React from "react";
    import { Button } from "antd";
    
    interface Greeting {
       name: string;
       firstName?: string;
       lastName?: string;
    }
    
    // 没有使用React.FC
    const HelloOld = (props: Greeting) => <Button>你好{props.name}</Button>;
    
    // 使用React.FC泛型类型
    const Hello: React.FC<Greeting> = (props) => {
       return (
          <Button>Hello {props.name}</Button>
       )
    };
    
    export { Hello, HelloOld };

    定义函数组件时,使用React.FC与不使用没有太多区别,没有为我们带来明显的好处,建议使用常规定义方式。关于使用与不使用的区别,详见 https://github.com/facebook/create-react-app/pull/8177

    有类型约束的类组件

    import React,{Fragment} from "react";
    import { Button } from "antd";
    
    interface Greeting {
       name: string;
       firstName?: string;
       lastName?: string;
    }
    interface State {
       count: number
    }
    
    // 泛型类型,第一个传入参数约束属性props,第二个约束状态state(内部数据)
    class HelloClass extends React.Component<Greeting, State> {
       state: State = {
          count: 0
       };
       static defaultProps = {  // 属性默认值
          firstName: "",
          lastName: "",
       };
    
       render() {
          return (
             <Fragment>
                <p>点击了{this.state.count}次</p>
                <Button onClick={()=>{this.setState({count: this.state.count+1})}}>Hello{this.props.name}Class</Button>
             </Fragment>
          );
       }
    }
    
    export default HelloClass;

    有类型约束的高阶组件

    import React from "react";
    import HelloClass from "./HelloClass";
    
    interface Loading {
       loading: boolean;
    }
    
    function HelloHoc<P>(params?: any) {
       return function<P>(WrappedComponent: React.ComponentType<P>) { // P表示被包装组件的属性的类型
          return class NewComponent extends React.Component<P & Loading>{ // 这里使用交叉类型,为新组件增加一些属性,接口Loading定义了新增的属性声明
             render(){
                return this.props.loading ? <div>Loading</div> : <WrappedComponent {...this.props as P}/>
    
             }
          }
       }
    }
    
    export default HelloHoc()(HelloClass);

    高阶组件在ts中使用会有比较多的类型问题,解决这些问题通常不会很顺利,而且会存在一些已知的bug,这不是高阶组件本身的问题,而是React声明文件还没有很好地兼容高阶组件的类型检查,更好的方式是使用Hooks

    有类型约束的Hooks

    import React, { useState, useEffect } from "react";
    import { Button } from "antd";
    
    interface Greeting {
       name: string;
       firstName?: string;
       lastName?: string;
    }
    
    const HelloHooks = (props: Greeting) => {
       const [ count, setCount ] = useState(0); // 设了初值,所以不用定义类型
       const [ text, setText ] = useState<string | null>(null);
    
       useEffect(()=>{
          count > 5 && setText("休息一下");
       },[count]); // 第二个参数的作用是,只有当count改变的时候,函数内的逻辑才会执行。
    
       return (
          <>
             <p>你点击了Hooks {count} 次 {text}</p>
             <Button onClick={()=>{setCount(count+1)}}>{props.name}</Button>
          </>
       );
    };
    
    export default HelloHooks;

    事件绑定

    class HelloClass extends React.Component<Greeting, State> {
       state: State = {
          count: 0
       };
    
       clickHandle = (e: React.MouseEvent) => { // 事件对象e的类型使用内置的合成事件。在回调函数中,e的属性都会无效
          e.persist(); // 将该事件从池中删除合成事件,可以正常使用
          console.log(e);
          // this.setState({count: this.state.count+1})
       };
    
       inputHandle = (e: React.FormEvent<HTMLInputElement>) => {
          // e.persist();
          console.log(e.currentTarget.value); // 此时编译器报错,认为没有value属性,需要指定<HTMLInputElement>泛型类型
          // console.log(e.target.value); // 仍然不行
       };
    
       render() {
          return (
             <Fragment>
                <p>点击了{this.state.count}次</p>
                <Button onClick={this.clickHandle}>Hello{this.props.name}Class</Button>
                <input onChange={this.inputHandle}/>
             </Fragment>
          );
       }
    }
  • 相关阅读:
    关于在pycharm下提示ModuleNotFoundError: No module named 'XXX' 的一种可能
    记录Python类与继承的一个错误
    JavaScript 中this 初步理解笔记
    Kibana6.x.x源码分析--如何自定义savedObjectType对象
    Kibana6.x.x源码分析--如何使用kibana的savedObjectType对象
    AngularJs依赖注入写法笔记
    Kibana6.x.x源码分析--ngReact使用
    Kibana6.x.x源码分析--Error: $injector:nomod Module Unavailable
    互联网时代,我们可以选择不做穷人
    ES6问题记录--Promise
  • 原文地址:https://www.cnblogs.com/V587Chinese/p/11520674.html
Copyright © 2020-2023  润新知