创建一个简单的线上机器人商店
创建一个项目,使用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为函数组件,<RobotProps>泛型类型,可写为{props},propt用来传递数据,此处使用解构赋值直接展开数据{ id, name, email }
const Robot: React.FC<RobotProps> = ({ id, name, email }) => {
return (
<li>
<img alt="robot" src={`https://robohash.org/${id}`} />
<h2>{name}</h2>
<p>{email}</p>
</li>
);
};
export default Robot;
2.使用组件
import './App.css';
//导入机器人数据
import robots from './mockdata/robots.json'
import Robot from './components/Robot';
function App() {
return (
<ul>
{robots.map(r => (
<Robot id={r.id} email={r.email} name={r.name}/>
))}
</ul>
);
}
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的模块化加载(隔离样式污染)
- 修改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'
<img src={logo} alt="logo" className={styles.appLogo} />
(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;
}