类型即正义: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 从入门到实践(序章)


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

查看所有标签

猜你喜欢:

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

Learn Python 3 the Hard Way

Learn Python 3 the Hard Way

Zed A. Shaw / Addison / 2017-7-7 / USD 30.74

You Will Learn Python 3! Zed Shaw has perfected the world’s best system for learning Python 3. Follow it and you will succeed—just like the millions of beginners Zed has taught to date! You bring t......一起来看看 《Learn Python 3 the Hard Way》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码