类型即正义:TypeScript 从入门到实践(序章)

栏目: IT技术 · 发布时间: 4年前

内容简介:本文所涉及的源代码都放在了此教程属于初始一个 React 应用的最佳方式那么一定是 React 官方维护的
类型即正义:TypeScript 从入门到实践(序章)
类型即正义:TypeScript 从入门到实践(序章)

@pftom

查看代码

准备代码

  1. 因为需要尽可能全且精炼的讲解 TypeScript 语法知识,所以我们需要一个恰到好处的实战项目,这一小节主要是用于讲解我们准备初始 TypeScript 版本的 React 项目代码的过程,在下一个小节中我们将会结合 React 项目代码,真正开始 TypeScript 语法的讲解。

本文所涉及的源代码都放在了 Github 或者 Gitee 上,如果您觉得我们写得还不错,希望您能给 :heart:这篇文章点赞+ Github ** 或 [ Gitee ]( https://gitee.com/tuture/typescript-tea ) 仓库加星❤**️哦~

此教程属于 React 前端工程师学习路线 的一部分,欢迎来 Star 一波,鼓励我们继续创作出更好的教程,持续更新中~

前提条件

  1. 确保你已经安装了 Node.js,可以访问官网安装: 官网地址
  2. 确保你已经了解基本的 React 开发知识,图雀社区有一篇很好的React 入门教程,你可以通过学习它很快的上手 React。
  3. 确保你有一定的命令行使用基础,包括使用 Npm (Node.js 包管理工具)来安装包。

初始化应用

初始一个 React 应用的最佳方式那么一定是 React 官方维护的 Create React App 脚手架了,我们打开终端,运行如下命令来初始化一个 TypeScript 版本的 React 应用:

$ npx create-react-app typescript-tea --template typescript

运行如上命令,命令行里面应该会有一系列输出,等待几分钟,就会提示已经初始化完成,并提供了对于的命令来帮助你开启项目,我们根据提示输入如下命令来开启项目:

$ cd typescript-tea
$ npm start

运行如上命令之后,会自动开启 Webpack 开发服务器,并打开浏览器窗户,访问 http://localhost:3000/ 来展示你的应用初始界面:

类型即正义:TypeScript 从入门到实践(序章)

如果看到这个界面,恭喜你 !成功创建一个 TypeScript 版本的 React 应用!

提示

在下文中,为了简化语言,我们统一称 TypeScript 为 TS。

引入 antd 组件库

实战驱动的技术学习能带给我们成就感,便捷好用的包可以加快我们的开发效率,好看的界面可以提高我们的审美能力,缓解学习疲劳。在这篇教程的讲解过程中,我们将通过 Ant Design 对应的 React 组件库 antd 来辅助我们项目的编写,使得我们可以专注于讲解 TS 的核心知识,而不被繁杂的界面语言所干扰,还能做出对应相应完成的目标功能。

提示

Ant Design 是蚂蚁金服孵化的一套企业级产品设计体系,提供了完备的 TS 类型定义,使得我们可以很方便的在 TS 项目中使用,在最近发布了 4.0 版本,致力于创造高效愉悦的工作体验。

除此之外 Ant Design 的周边生态也很丰富:

  • 包括新一代数据可视化解决方案: AntV
  • 一个基于 Preact / React / React Native 的 UI 组件库: Ant Design Mobile
  • 开箱即用的中台前端/设计解决方案: Ant Design Pro
  • 插画设计: 海兔
  • 一款为设计者提升工作效率的 Sketch 工具集 : Kitchen

后面图雀社区计划围绕 Ant Design 生态撰写一系列教程,帮助大家提高设计、开发效率,敬请期待!:v:

安装依赖

好了,大致介绍了 antd 组件库及 Ant Design 周边之后,我们马上来写代码引入 antd,打开命令行,在其中输入如下命令:

$ npm install antd

运行上面的命令安装完依赖之后就可以在项目中使用了,但是为了更好的定制样式和按需引用以减小打包之后的包体积,我们还需要做一点定制化的操作,打开命令行,依次安装如下依赖:

$ npm install react-app-rewired customize-cra babel-plugin-import less less-loader

注意到上面我们安装了很多包,我们来依次解释一下上面各种包的意思:

  • react-app-rewired:用来定制化 Create React App (CRA)脚手架的一些配置,比如 Webpack、Babel 等,因为 CRA 它是一个封闭的黑盒,不允许开发者直接定制,但有时候我们需要对配置做一些修改,比如这里需要配置 antd 的按需引用。
  • customize-cra:是 CRA 在发布 2.0 之后出来的一个辅助 react-app-rewired 更方便定制 CRA 的 Webpack 配置的一个库,它提供了一些开箱即用的 API。
  • babel-plugin-import:是配置可供开发者按需引用 antd 组件的一个 Babel 插件
  • less 和 less-loader:是我们用于定制化 antd 的主题需要的 Webpack loader,因为 antd 使用 less 作为样式化语言。

最后我们安装一个在 Ant Design 4.0 拆分出去的 icons 包,可以用来按需引用 icons,进一步减少最后的打包体积,继续在命令行运行如下命令:

$ npm install @ant-design/icons

大功告成!现在我们所有的依赖以及安装完成。接下来就需要改写一下 CRA 之前通过 react-scripts 跑开发构建的流程,用我们安装的 react-app-rewired 脚本来替换它,当安装完了所以依赖,以及用 react-app-rewired 替换 react-scripts 之后,我们的 package.json 文件应该是下面的样子:

package.json 查看完整代码
// ...
  "version": "0.1.0",
  "private": true,
  "dependencies": {
[tuture-add]    "@ant-design/icons": "^4.0.2",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "@types/jest": "^24.0.0",
    "@types/node": "^12.0.0",
    "@types/react": "^16.9.0",
    "@types/react-dom": "^16.9.0",
[tuture-add]    "antd": "^4.0.0",
[tuture-add]    "babel-plugin-import": "^1.13.0",
[tuture-add]    "customize-cra": "^0.9.1",
[tuture-add]    "less": "^3.11.1",
[tuture-add]    "less-loader": "^5.0.0",
    "react": "^16.13.0",
[tuture-add]    "react-app-rewired": "^2.1.5",
    "react-dom": "^16.13.0",
    "react-scripts": "3.4.0",
    "typescript": "~3.7.2"
  },
  "scripts": {
[tuture-del]    "start": "react-scripts start",
[tuture-del]    "build": "react-scripts build",
[tuture-del]    "test": "react-scripts test",
[tuture-add]    "start": "react-app-rewired start",
[tuture-add]    "build": "react-app-rewired build",
[tuture-add]    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  },
  // ...

修改配置

安装完依赖之后,我们要确保对应改写 CRA 流程的配置生效,我们需要根据 react-app-rewired 的文档说明在根目录下建立 config-overrides.js 文件,并在其中编写如下的内容:

config-overrides.js 查看完整代码
const { override, fixBabelImports, addLessLoader } = require("customize-cra");
const darkThemeVars = require("antd/dist/dark-theme");

module.exports = override(
  fixBabelImports("import", {
    libraryName: "antd",
    libraryDirectory: "es",
    style: true
  }),
  addLessLoader({
    javascriptEnabled: true,
    modifyVars: {
      hack: `true;@import "${require.resolve(
        "antd/lib/style/color/colorPalette.less"
      )}";`,
      ...darkThemeVars,
      "@primary-color": "#02b875"
    }
  })
);

可以看到,上面的代码主要是导出一个用于修改 Webpack 配置的对象,使用 override API,接收两个修改配置的函数调用, fixBabelImports 用于配置 antd 的按需引用, addLessLoader 用于配置 antd 的主题,这里我们使用了 Ant Design 4.0 新带来的 Dark Mode(暗色模式),然后配置了主题色为图雀社区的主题色: #02b875 ,代表希望的绿色。:laughing:

自此,我们就引入了 antd 组件库,并进行了按需配置使用以及配置主题色和使用了 Ant Design 最新的暗色主题 – Dark Mode。

编写初始代码

准备逻辑部分

接下来,我们将使用 antd 帮助我们快速的编写一下我们即将实现的待办事项的界面,打开 src/App.tsx ,对其中的代码做出对应的修改如下:

src/App.tsx 查看完整代码
[tuture-del]import React from 'react';
[tuture-del]import logo from './logo.svg';
[tuture-del]import './App.css';
[tuture-add]import React, { useState, useRef } from "react";
[tuture-add]import {
[tuture-add]  List,
[tuture-add]  Avatar,
[tuture-add]  Button,
[tuture-add]  Typography,
[tuture-add]  Form,
[tuture-add]  Input,
[tuture-add]  Select,
[tuture-add]  DatePicker,
[tuture-add]  Menu,
[tuture-add]  Dropdown,
[tuture-add]  Tabs
[tuture-add]} from "antd";
[tuture-add]import { DownOutlined } from "@ant-design/icons";

[tuture-del]function App() {
[tuture-add]import "./App.css";
[tuture-add]import logo from "./logo.svg";
[tuture-add] 
[tuture-add]const { Title } = Typography;
[tuture-add]const { Option } = Select;
[tuture-add]const { TabPane } = Tabs;
[tuture-add] 
[tuture-add]const todoListData = [
[tuture-add]  {
[tuture-add]    content: "图雀社区:汇聚精彩的免费实战教程",
[tuture-add]    user: "mRcfps",
[tuture-add]    time: "2020年3月2日 19:34",
[tuture-add]    isCompleted: false
[tuture-add]  },
[tuture-add]  {
[tuture-add]    content: "图雀社区:汇聚精彩的免费实战教程",
[tuture-add]    user: "pftom",
[tuture-add]    time: "2020年3月2日 19:34",
[tuture-add]    isCompleted: false
[tuture-add]  },
[tuture-add]  {
[tuture-add]    content: "图雀社区:汇聚精彩的免费实战教程",
[tuture-add]    user: "Holy",
[tuture-add]    time: "2020年3月2日 19:34",
[tuture-add]    isCompleted: false
[tuture-add]  },
[tuture-add]  {
[tuture-add]    content: "图雀社区:汇聚精彩的免费实战教程",
[tuture-add]    user: "crxk",
[tuture-add]    time: "2020年3月2日 19:34",
[tuture-add]    isCompleted: false
[tuture-add]  },
[tuture-add]  {
[tuture-add]    content: "图雀社区:汇聚精彩的免费实战教程",
[tuture-add]    user: "Pony",
[tuture-add]    time: "2020年3月2日 19:34",
[tuture-add]    isCompleted: false
[tuture-add]  }
[tuture-add]];
[tuture-add] 
[tuture-add]const userList = [
[tuture-add]  {
[tuture-add]    id: "666666666",
[tuture-add]    name: "图雀社区",
[tuture-add]    avatar: "https://avatars0.githubusercontent.com/u/39240800?s=60&v=4"
[tuture-add]  },
[tuture-add]  {
[tuture-add]    id: "23410977",
[tuture-add]    name: "mRcfps",
[tuture-add]    avatar: "https://avatars0.githubusercontent.com/u/23410977?s=96&v=4"
[tuture-add]  },
[tuture-add]  {
[tuture-add]    id: "25455350",
[tuture-add]    name: "crxk",
[tuture-add]    avatar: "https://avatars1.githubusercontent.com/u/25455350?s=96&v=4"
[tuture-add]  },
[tuture-add]  {
[tuture-add]    id: "23410977",
[tuture-add]    name: "pftom",
[tuture-add]    avatar: "https://avatars0.githubusercontent.com/u/23410977?s=96&v=4"
[tuture-add]  },
[tuture-add]  {
[tuture-add]    id: "58352313",
[tuture-add]    name: "holy",
[tuture-add]    avatar: "https://avatars0.githubusercontent.com/u/58352313?s=96&v=4"
[tuture-add]  }
[tuture-add]];
[tuture-add] 
[tuture-add]const menu = (
[tuture-add]  <Menu>
[tuture-add]    <Menu.Item>完成</Menu.Item>
[tuture-add]    <Menu.Item>删除</Menu.Item>
[tuture-add]  </Menu>
[tuture-add]);
[tuture-add] 
[tuture-add]const TodoInput = ({ value = {} }) => {
  return (
[tuture-del]    <div className="App">
[tuture-del]      <header className="App-header">
[tuture-del]        <img src={logo} className="App-logo" alt="logo" />
[tuture-del]        <p>
[tuture-del]          Edit <code>src/App.tsx</code> and save to reload.
[tuture-del]        </p>
[tuture-del]        <a
[tuture-del]          className="App-link"
[tuture-del]          href="https://reactjs.org"
[tuture-del]          target="_blank"
[tuture-del]          rel="noopener noreferrer"
[tuture-add]    <div className="todoInput">
[tuture-add]      <Input type="text" placeholder="输入待办事项内容" />
[tuture-add]      <Select style={{ width: 80 }} size="small" defaultValue="666666666">
[tuture-add]        {userList.map(user => (
[tuture-add]          <Option value={user.id}>{user.name}</Option>
[tuture-add]        ))}
[tuture-add]      </Select>
[tuture-add]      <DatePicker
[tuture-add]        size="small"
[tuture-add]        style={{ marginLeft: "16px", marginRight: "16px" }}
[tuture-add]      />
[tuture-add]    </div>
[tuture-add]  );
[tuture-add]};
[tuture-add] 
[tuture-add]function TodoList() {
[tuture-add]  return (
[tuture-add]    <List
[tuture-add]      className="demo-loadmore-list"
[tuture-add]      itemLayout="horizontal"
[tuture-add]      dataSource={todoListData}
[tuture-add]      renderItem={item => (
[tuture-add]        <List.Item
[tuture-add]          actions={[
[tuture-add]            <Dropdown overlay={menu}>
[tuture-add]              <a key="list-loadmore-more">
[tuture-add]                操作 <DownOutlined />
[tuture-add]              </a>
[tuture-add]            </Dropdown>
[tuture-add]          ]}
        >
[tuture-del]          Learn React
[tuture-del]        </a>
[tuture-del]      </header>
[tuture-add]          <List.Item.Meta
[tuture-add]            avatar={
[tuture-add]              <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
[tuture-add]            }
[tuture-add]            title={<a href="https://ant.design">{item.user}</a>}
[tuture-add]            description={item.time}
[tuture-add]          />
[tuture-add]          <div>{item.content}</div>
[tuture-add]        </List.Item>
[tuture-add]      )}
[tuture-add]    />
[tuture-add]  );
[tuture-add]}
[tuture-add] 
[tuture-add]function App() {
[tuture-add]  const callback = () => {};
[tuture-add] 
[tuture-add]  const onFinish = () => {};
[tuture-add]  const ref = useRef(null);
[tuture-add] 
[tuture-add]  return (
[tuture-add]    <div className="App" ref={ref}>
[tuture-add]      <div className="container header">
[tuture-add]        <img src={logo} alt="" />
[tuture-add]        <Title level={3}>图雀社区:汇聚精彩的免费实战教程</Title>
[tuture-add]      </div>
[tuture-add]      <div className="container">
[tuture-add]        <Form onFinish={onFinish}>
[tuture-add]          <Form.Item name="todo">
[tuture-add]            <TodoInput />
[tuture-add]          </Form.Item>
[tuture-add]        </Form>
[tuture-add]      </div>
[tuture-add]      <div className="container">
[tuture-add]        <Tabs onChange={callback} type="card">
[tuture-add]          <TabPane tab="所有" key="1">
[tuture-add]            <TodoList />
[tuture-add]          </TabPane>
[tuture-add]          <TabPane tab="进行中" key="2">
[tuture-add]            <TodoList />
[tuture-add]          </TabPane>
[tuture-add]          <TabPane tab="已完成" key="3">
[tuture-add]            <TodoList />
[tuture-add]          </TabPane>
[tuture-add]        </Tabs>
[tuture-add]      </div>
    </div>
  );
}
 // ...

上面的代码主要就是一系列初始数据的准备,antd 组件的使用,编写起来的大致轮廓,还没有涉及到任何的 TS 语法,但这个是我们开始项目的基础,读者只需要进行简单的复制放进现有的 typescript-tea 项目中对应的 src/App.tsx 中即可。

准备样式部分

准备了逻辑代码之后,为了让我们最后的待办事项在样式上更美观一点,也利于我们讲解时的操作,我们需要给项目加一点样式,打开 src/App.css 对其中的代码做出对应的修改如下:

src/App.css 查看完整代码
.App {
[tuture-del]  text-align: center;
[tuture-add]  display: flex;
[tuture-add]  flex-direction: column;
[tuture-add]  align-items: center;
[tuture-add]  padding-top: 60px;
[tuture-add]}
[tuture-add] 
[tuture-add].container {
[tuture-add]  width: 600px;
}

[tuture-del].App-logo {
[tuture-del]  height: 40vmin;
[tuture-del]  pointer-events: none;
[tuture-add].header {
[tuture-add]  text-align: center;
[tuture-add]  margin-bottom: 56px;
}

[tuture-del]@media (prefers-reduced-motion: no-preference) {
[tuture-del]  .App-logo {
[tuture-del]    animation: App-logo-spin infinite 20s linear;
[tuture-del]  }
[tuture-add].header img {
[tuture-add]  width: 160px;
[tuture-add]  height: 160px;
[tuture-add]  margin-bottom: 24px;
}

[tuture-del].App-header {
[tuture-del]  background-color: #282c34;
[tuture-del]  min-height: 100vh;
[tuture-add].todoInput {
  display: flex;
[tuture-del]  flex-direction: column;
[tuture-add]  flex-direction: row;
  align-items: center;
[tuture-del]  justify-content: center;
[tuture-del]  font-size: calc(10px + 2vmin);
[tuture-del]  color: white;
[tuture-del]}
[tuture-del] 
[tuture-del].App-link {
[tuture-del]  color: #61dafb;
[tuture-add]  height: 40px;
[tuture-add]  border: 1px solid #434343;
}

[tuture-del]@keyframes App-logo-spin {
[tuture-del]  from {
[tuture-del]    transform: rotate(0deg);
[tuture-del]  }
[tuture-del]  to {
[tuture-del]    transform: rotate(360deg);
[tuture-del]  }
[tuture-add].todoInput input {
[tuture-add]  border: none;
}

好了!所有的准备工作已经就绪,在开始下一节真正的 TS 学习之前,我们先来回顾一下我们在这个小节中所完成的工作:

  • 使用 CRA 的 TypeScript 脚本初始化了一个 TS 版的 React 项目
  • 安装了 antd 组件库,并使用 react-app-rewired 替换默认的 react-scripts 来完成对 CRA 的 Webpack 配置进行修改,以是我们可以获得 antd 组件的按需引用和主题定制的功能
  • 准备了初始待办事项代码的逻辑部分和样式部分

我们在前面铺垫了大量的 TypeScript 的优点以及花了不少笔墨来准备初始代码,想必读到这里的读者们可能已经等不及要马上见识一下 TS 的庐山真面目了吧!马上就来啦!

本文所涉及的源代码都放在了 Github 或者 Gitee 上,如果您觉得我们写得还不错,希望您能给 :heart:这篇文章点赞+ Github ** 或 [ Gitee ]( https://gitee.com/tuture/typescript-tea ) 仓库加星❤**️哦~

类型即正义:TypeScript 从入门到实践(序章)


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

硅谷增长黑客实战笔记

硅谷增长黑客实战笔记

曲卉 / 机械工业出版社 / 2018-4-10 / 65.00元

增长黑客这个词源于硅谷,简单说,这是一群以数据驱动营销、以迭代验证策略,通过技术手段实现爆发式增长的新型人才。近年来,互联网公司意识到这一角色可以发挥四两拨千斤的作用,因此对该职位的需求也如井喷式增长。 本书作者曾在增长黑客之父肖恩•埃利斯麾下担任增长负责人,用亲身经历为你总结出增长黑客必备的套路、内力和兵法。本书不仅有逻辑清晰的理论体系、干货满满的实践心得,还有Pinterest、SoFi......一起来看看 《硅谷增长黑客实战笔记》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码