umi ts 升级


umi配置ts的过程

背景(为什么要配置TS)

1.本来项目是一个老的项目,之前有过升级但是由于大家技术水平的不统一,TS学习成本高,导致一直在搁浅中。
2.由于现在ts的普及以及最近代码质量越来越难以把控,所以引入ts是控制质量的一种方式。

ts有啥好呢?

1.可读性:类型明确,不需要额外注释类型;看到类型就知道怎么用;
2.可维护性:在编译间断就可以发现错误,避免认为错误出现;
3.兼容性:兼容js语法;可以直接将*.js改为*.ts使用;完全支持ES6规范;
4.第三方库:兼容第三方库,即使第三方库不是用tst写的,也可以编写单独的类型文件供ts读取;

ts有啥不好呢?

1.从纯js转过来有一定的难度,好多写法类似java;
2.类型定义比较繁琐和js相比;
3.一些库兼容性不是很好;
4.需要额外的构建工作量;

umi怎么配置

  • 新的umi 3 create工具包会自动帮你配好。老的项目需要手动配置;我们这里主要介绍老项目的配置;

  • 不管是老项目还是新项目,我们至少都要懂他的配置,这样便于我们后期如果项目变庞大复杂了,这是对项目进行优化;

umi3脚手架配置

按umi标准文档配置就可以了;
umi create-app文档:https://umijs.org/zh-CN/docs

    $ yarn create @umijs/umi-app
      Copy:  .editorconfig
      Write: .gitignore
      Copy:  .prettierignore
      Copy:  .prettierrc
      Write: .umirc.ts
      Copy:  mock/.gitkeep
      Write: package.json
      Copy:  README.md
      Copy:  src/pages/index.less
      Copy:  src/pages/index.tsx
      Copy:  tsconfig.json
      Copy:  typings.d.ts
      .
      .
      .

目录结构

    .
    ├── package.json
    ├── .umirc.ts
    ├── .env
    ├── dist
    ├── mock
    ├── public
    └── src
        ├── .umi
        ├── layouts/index.tsx
        ├── pages
            ├── index.less
            └── index.tsx
        └── app.ts
  balabala ... 这里省略一万字(具体看文档就可以了)
umi老的项目配置

(1).umirc.ts
官方解释: 配置文件,包含 umi 内置功能和插件的配置。
话不多说,和老的.js一样并且可以共用。即运行时配置。

(2)tsconfig.json
官方解释: TypeScript项目的根目录;
我的解释:用来配置编译ts项目的根文件和编译配置;

  {
    "compilerOptions": {
      "target": "esnext",
      "module": "esnext",
      "moduleResolution": "node",
      "importHelpers": true,
      "jsx": "react",
      "esModuleInterop": true,
      "sourceMap": true,
      "baseUrl": ".",
      "strict": true,
      "allowUnreachableCode":false, // 不报告执行不到的代码错误。
      "allowJs": true, //允许编译javascript文件。
      "allowSyntheticDefaultImports": true, //允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。
      "experimentalDecorators": true,
      "outDir": "dist/",
      "paths": {
        "@/*": ["src/*"],
        "@*": ["src/*"],
        "@SDVariableJS": ["config/variableConfig.js"],
      }
    },
    "files": [
      "core.ts",
      "sys.ts",
      "types.ts",
    ],
    "include":[],
    "exclude": ["node_modules", "dist"]
  }

常用的参数配置:

allowUnreachableCode:默认值-false 解释:不报告执行不到的代码错误。
allowJs:默认值-true 解释:允许编译javascript文件。
allowSyntheticDefaultImports:默认值-true 解释:允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。
noImplicitUseStrict:默认值-alse 解释:模块输出中不包含 “use strict”指令。
alwaysStrict:默认值-false 解释:以严格模式解析并为每个源文件生成 “use strict”语句
checkJs:默认值-false 解释:在.js文件中报告错误。与 allowJs配合使用。

更多参数配置见:https://www.tslang.cn/docs/handbook/compiler-options.html

(3)typings.d.ts

释义:存放一些声明,类似于C/C++的.h头文件。(不知道大家理解么,写过C的应该懂这个)

  • TypeScript相比JavaScript增加了类型声明。这些类型声明帮助编译器识别类型,从而防止开发者“搬起石头砸自己的脚”。原则上TypeScript 需要开发者做到先声明后使用。这就导致开发者在调用很多原生接口(浏览器、Node.js)或者第三方模块的时候,因为某些全局变量或者对象的方法并没有声明过,导致编译器的类型检查失败。

  • 用ts写的模块在发布的时候仍然是用js发布;
    这就导致一个问题:ts 那么多类型数据都没了,所以需要一个*.d.ts文件来标记某个js库里面对象的类型然后typings就是一个网络上的d.ts数据库;

  • *.d.ts类型定义文件,我感觉现在对我的用处就是编辑器的智能提示

    (4)tslint.json

    释义:保存了要使用的代码检查器的设置。
    TSLint 对TypeScript 支持得很好,并且如果你使用的是 VsCode IDE,还有出色的插件支持。

    tslint.json

    {
    "defaultSeverity": "error",
    "extends": [
      "tslint:latest",
      "tslint-react",
      "tslint-config-prettier" // 安装tslint-config-prettier后,tslint-config-prettier禁用TSLint的所有格式设置规则, TSLint 和 prettier在代码格式化规则上就不会有冲突了
    ],
    "jsRules": {},
    "rules": {
      "object-literal-sort-keys": false,
      "no-console": true,
      "jsx-no-lambda": false,
      "no-submodule-imports": false,
      "no-implicit-dependencies": false
    }
    }

    tslint保存时校验配置

    "editor.codeActionsOnSave": {
    
      "source.fixAll.eslint": true, // For ESLint
    
      "source.fixAll.tslint": true, // For TSLint
    
      "source.fixAll.stylelint": true, // For Stylelint
    }

    prettier保存时校验配置

    "editor.formatOnSave": true,
  • ps: 使用tslint-config-prettier关闭tslint中有关格式的规则,避免tslint与prettier在格式规则上产生冲突。目前我们的项目中(.jsx)中没有开启这一项。

当按ctrl+s保存代码时,tslint插件会自动按照默认配置文件(项目根目录下的tslint.json)检查代码错误,prettier插件会自动按照默认配置文件(项目根目录下的.prettierrc)检查代码风格,并自动矫正。(不建议使用)

VSCode配置

建议安装tsLint 插件插件,vsCode中直接搜索安装;

  • ps:这个库可esLint库可以共存,但是需要进行配置,保证在.jsx/.tsx文件中只有一个生效,不然错误提示会有误报的情况。
    具体配置地址:https://github.com/Microsoft/typescript-tslint-plugin;

    到此时,我们的环境就配好了,接下来写一个小的React的demo.tsx吧;

React typescript写法

几个概念React.FC:
-FC = Functional Component
-SFC = Stateless Functional Component (已弃用)

学习typescript的基本语法,具体ts见:https://www.runoob.com/typescript/ts-variables.html

  • ps: 我有视频,如有需要可找我要哈😄;

    有了以上typescrt姿势,我们就可以开始写ts代码了。⛽️

    下面是我写的两种常见写法的demo;

泛型组件写法(对标Class写法)

import React from 'react';
import UseInfo from "./UseInfo"; // 引用其他组件(可以是.tsx,也可以是.jsx)
import style from './test.less'; // 引用样式文件

function getExclamationMarks(numChars: number) {
  return Array(numChars + 1).join('!');
}

interface Props {
  name: string;
  enthusiasmLevel: number;
}
interface State {
  now: string,
}

class Test extends React.Component<Props, State> {
  constructor(props:Props) {
    super(props);
    this.state = {
      now: "fff",
    };
  }
  public clickTest = (x:string) => {
    console.log(x)
    this.setState({now: '###'});
  }
  render() {
    const { name, enthusiasmLevel = 1 } = this.props;
    const { now } = this.state;

    console.log('@@@@@');
    const hello : string = 111
    console.log(hello)

    if (enthusiasmLevel <= 0) {
      throw new Error('You could be a little more enthusiastic. :D');
    }

    return (
      <div className="hello">
        <UseInfo />
        <div className="greeting">
          {`Hello ${name + getExclamationMarks(enthusiasmLevel)}`}
        </div>
        <div className={style.button} onClick={()=>this.clickTest(now)}></div>
      </div>
    );
  }
}
export default Test;
Hooks写法
import React, { Fragment, useState } from 'react';
import UseInfo from "./UseInfo"; // 引用其他组件(可以是.tsx,也可以是.jsx)
import style from './base.less'; // 引用样式文件

interface IProps {
    changeTitle?: () => void;
}

const Auth = (props: IProps) => {
    const [houseTitle, setHoueseTitle] = useState<string>('')
    return (<Fragment>
      <useInfo />
      <div>
        <input
            type="text"
            className={style.demo1}
            placeholder={'please input'}
            value={houseTitle}
            onChange={changeTitle}
        />
    </div>
    </Fragment>)
    function changeTitle(e:any) { // 房屋标题
        setHoueseTitle(e.target.value)
    }
}
export default Auth

好了,我们的一个完整的umi支持ts写法到这里就结束了,希望大家都学会了。

结语

随着前端技术的发展。弱类型基本不能满足我们日益复杂的业务,强类型语言是未来的趋势。
Framework - Angular2、UI - ant-design、library - RxJS等项目已经都迁移到typescript了,我们还不跟进吗。。。


文章作者: Duke
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Duke !
评论
 上一篇
使用 D3.js 创建可交互的柱状图 使用 D3.js 创建可交互的柱状图
我会在此文中介绍使用 D3.js 的过程,以及通过一个简单的柱状图示例演示库的基本使用。读完此文后,你将学到如何轻松创建类似的 D3.js
2021-02-20
下一篇 
ios safari 返回时不执行代码问题解析 ios safari 返回时不执行代码问题解析
最近在调试钉钉/企业微信时发现一个问题,在ios上使用返回键时,上一页的内容不执行js代码,导致react的生命周期,包componentDidMount都不执行,由于这两个平台都没有开发者工具,无法进行调试着实废了一番功夫。
2020-12-22