创建一个简单的线上机器人商店


创建一个项目,使用TS模板:
添加TS模板: https://zh-hans.reactjs.org/docs/static-type-checking.html#adding-typescript-to-a-project
jsx简介:
https://zh-hans.reactjs.org/docs/introducing-jsx.html
(不管是原生js文件还是jsx文件,都没法直接在浏览器运行,而是需要babel转化es标准下的代码,项目中使用哪种类型的文件都是可以的。本项目使用TSX)
ts简单的来说就是给js加上了类型

结构

1.创建robot组件(tsx文件)

import React from "react";

interface RobotProps {
  id: number;
  name: string;
  email: string;
}
// 定义Robot为函数组件,泛型类型,可写为{props},propt用来传递数据,此处使用解构赋值直接展开数据{ id, name, email }
const Robot: React.FC = ({ id, name, email }) => {
  return (
    
  • robot

    {name}

    {email}

  • ); }; export default Robot;

    2.使用组件

    import './App.css';
    //导入机器人数据
    import robots from './mockdata/robots.json'
    import Robot from './components/Robot';
    function App() {
      return (
       
      {robots.map(r => ( ))}
    ); } export default App;

    机器人数据参考:
    若无法识别json文件,可修改tsconfig.json解决,添加"moduleResolution": "node", "resolveJsonModule": true

    [{
        "id": 1,
        "name": "Leanne Graham",
        "username": "Bret",
        "email": "Sincere@april.biz",
        "address": {
          "street": "Kulas Light",
          "suite": "Apt. 556",
          "city": "Gwenborough",
          "zipcode": "92998-3874",
          "geo": {
            "lat": "-37.3159",
            "lng": "81.1496"
          }
        },
        "phone": "1-770-736-8031 x56442",
        "website": "hildegard.org",
        "company": {
          "name": "Romaguera-Crona",
          "catchPhrase": "Multi-layered client-server neural-net",
          "bs": "harness real-time e-markets"
        }
      }]
    

    样式

    模组CSS文件

    • css文件与component文件放在同一目录下
    • 命名规范 *.module.css
      react默认构建了全局样式import'./index.css'
      import整个文件,默认会引入整个css文件,有可能会造成全局污染,我们可以按需引入import style from './index.css'
      以App.tsx作为案例处理css的模块化加载(隔离样式污染)
    1. 修改app.css的引用模式
      import'./App.css' 改为
      import styles from './App.css'
      typescript无法识别css格式的文件
      给css文件加上TS的定义声明
      .d.ts文件
      只包含类型定义,不包含逻辑
      不会被编译,也不会被webpack打包
    declare module "*.css" {
      const css: { [key: string]: string };
      export default css;
    }
    

    声明所有.css后缀的文件,都会被定义为这种类型,接下来就可以通过访问对象的形式去使用css样式了。(JSS/CSS in JS)
    2. 修改app.css为app.module.css
    在react中,为了避免与es6中的类关键词class产生冲突,必须使用className关键词。

    安装插件(可忽略)

    npm install typescript-plugin-css-modules --save-dev

    配置

    本地编译器配置,添加.vscode文件夹,添加settings.json文件
    文件中输入:

    {
    	"typescript.tsdk": "node_modules/typescript/lib",
    	"typescript.enablePromptUseWorkspaceTsdk": true
    }
    

    配置完成后,会发现多了提示功能:

    补充代码

    以同样的方式给robot.tsx文件添加模块化样式,代码如下:

    .cardContainer {
        display: flex;
        flex-direction: column;
        background-color: #00BDAB;
        border: 1px solid grey;
        border-radius: 5px;
        padding: 25px;
        cursor: pointer;
        backface-visibility: hidden;
        transform: translateZ(0);
        transition: transform 0.25s ease-out;
    }
    
    .cardContainer:hover {
        transform: scale(1.05);
    }
    

    加载媒体资源与字体

    建立存储静态资源的目录结构

    媒体资源可直接引用:

    import logo from './assets/images/logo.svg'
    logo
    

    (window系统,点击ctrl+鼠标点击logo,可以进入到react-app.d.ts文件,可以看到react已经默认定义了svg在内的一些文件类型)
    字体资源:
    搜索免费字体,随意下载字体资源.tff文件
    在index.css文件中定义为全局字体

    @font-face {
        font-family: 'Slidefu';
        src: local('Slidefu'), url(./assets/fonts/Slidefu-Regular-2.ttf) format('truetype');
    }
    

    标题一使用该字体:

    h1 {
        font-family: 'Slidefu';
        font-size: 72px;
    }
    

    补充App文件样式代码:

    .app {
        text-align: center;
    }
    
    .appHeader {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        margin-top: 36px;
        margin-bottom: 24px;
    }
    
    .appLogo {
        height: 10vmin;
        pointer-events: none;
    }
    
    h1 {
        font-family: 'Slidefu';
        font-size: 72px;
    }
    
    @media (prefers-reduced-motion: no-preference) {
        .appLogo {
            animation: App-logo-spin infinite 20s linear;
        }
    }
    
    .robotList {
        width: 85vw;
        display: grid;
        grid-template-columns: 1fr 1fr 1fr 1fr;
        grid-gap: 20px;
    }
    

    image