1.新建react+ts项目
npx create-react-app <appname> --template typescript
2.将本地新建项目push到远程仓库 新建远程仓库 打开本地项目目录,把当前目录下的已有文件全部加到刚刚新建的git仓库中 执行 git add . 提交加入的文件,并书写描述信息 git commit -m "item init" 将本地仓库与远程仓库关联起来 git remote add origin 远程仓库地址 把本地仓库的内容push到远程仓库 git push -u origin master 3.修改tsconfig.json文件 添加 "baseUrl": "./src", //配置绝对路径指向 注意:(4-6)步骤可以不做(是部分格式化配置工程化提交规范,暂时未理清楚,容易发生错误,后续补充) 4.安装格式化工具Prettier yarn add --dev --exact prettier 创建格式化配置文件 echo {}> .prettierrc.json 新建prettierignore文件 .prettierignore 填入内容如下: Ignore artifacts: build coverage 之后就可以用 yarn prettier --write . 去格式化代码了 团队协作开发时,为了提交前将代码格式进行统一自动化格式化处理 需要使用到 Pre-commit Hook 执行 npx mrm@2 lint-staged 将会在package.json文件scripts中多一行代码 prepare": "husky install" "devDependencies": { "husky": "^7.0.4", "lint-staged": "^12.3.4", "prettier": "2.5.1" }, 这里表示需要格式化的文件后缀,我们需要把ts,tsx结尾的添加上去 "lint-staged": { "*.{js,css,md,ts,tsx}": "prettier --write" } 将生成的.husky目录添加到git里面 5.因为本身项目创建会有eslint配置,这将会和我们的prettier配置冲突 因此需要专门为eslint进行配置 npm install --save-dev eslint-config-prettier 安装完成后在package.json修改,将prettier添加到eslint中 "eslintConfig": { "extends": [ "react-app", "react-app/jest", "prettier" ] //表示用prettier规则覆盖了eslint部分规则 }, 6.配置 commitlint 规范工程--检测commit message 是否符合规范 npm install --save-dev @commitlint/config-conventional @commitlint/cli 添加commitlint.config.js文件定义规范,由于以下命令创建的文件编码格式非utf-8,提交时可能会报错。 所以推荐项目根目录手动创建commitlint.config.js文件后,复制粘贴module.exports = {extends: ['@commitlint/config-conventional']}; echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"' 就会在.husky目录下新增一个commit-msg文件 使用该命令取消校验: git commit -m "工程列表" --no-verify 7.安装json-server npm install -g json-server 全局安装 npm install json-server -D项目中安装 再新建目录json_server_mock __表示辅助存在的目录 __json_server_mock__ 该目录下创建db.json文件 里面可以填入内容如 { "users":[] } 修改package.json文件的scripts,添加 "json-server": "json-server __json_server_mock__/db.json --watch" "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "prepare": "husky install", "json-server": "json-server __json_server_mock__/db.json --watch --port 3001" } --port 指定端口号 最后执行 npm run json-server 就能启动mock服务了 8.创建.env 和.env.develop文件 在里面配置接口api请求地址 REACT_APP_API_URL = http://localhost:3001 引用时候: const apiUrl = process.env.REACT_APP_API_URL 9.处理发请求时参数为空 fetch(`${apiUrl}/projects?name=${param.name}&personId=${param.personId}`) 在src下新建utils目录 新建index.js文件,内容如下: export const isFalsy = (value) => value === 0 ? false: !value //将0排除后判断参数的bool值 //在一个函数里,改变传入的对象本身是不好的 export const cleanObject = (object) =>{ // Object.assign({},object) const result = {...object} Object.keys(result ).forEach(key=>{ const value = result [key] if(isFalsy(value)) { delete result[key] } }) return result } 安装qs插件 npm install qs --save-dev 最终请求路径替换成: fetch(`${apiUrl}/projects?${qs.stringify(cleanObject(param))}`)
最后建成的文件目录
使用jsonServer进行mock请求,以下写了一个小demo
db.json:
{
"users": [
{
"id": 1,
"name": "高修文"
},
{
"id": 2,
"name": "熊天成"
},
{
"id": 3,
"name": "郑华"
},
{
"id": 4,
"name": "王文静"
}
],
"projects": [
{
"id": 1,
"name": "骑手管理",
"personId": 1,
"organization": "外卖组",
"created": 1604989757139
},
{
"id": 2,
"name": "团购 APP",
"personId": 2,
"organization": "团购组",
"created": 1604989757139
},
{
"id": 3,
"name": "物料管理系统",
"personId": 2,
"organization": "物料组",
"created": 1546300800000
},
{
"id": 4,
"name": "总部管理系统",
"personId": 3,
"organization": "总部",
"created": 1604980000011
},
{
"id": 5,
"name": "送餐路线规划系统",
"personId": 4,
"organization": "外卖组",
"created": 1546900800000
}
]
}
index.jsx:
import React from "react";
import {cleanObject} from "../../utils";
import {SearchPanel} from "./search-panel";
import {List} from "./list";
import * as qs from "qs";
import {useEffect, useState} from "react";
const apiUrl = process.env.REACT_APP_API_URL
export const ProjectListScreen = () => {
const [param, setParam] = useState({
name: '',
personId: ''
})
const [users, setUsers] = useState([])
const [list, setList] = useState([])
useEffect(() => {
fetch(`${apiUrl}/projects?${qs.stringify(cleanObject(param))}`).then(async response => {
console.log(response)
if (response.ok) {
setList(await response.json())
}
})
}, [param])
useEffect(() => {
fetch(`${apiUrl}/users`).then(async response => {
console.log(response)
if (response.ok) {
setUsers(await response.json())
}
})
},[])
return <div>
<SearchPanel param={param} setParam={setParam} users={users}/>
<List list={list} users={users}/>
</div>
}
list.jsx:
import React from "react";
export const List = ({list, users}) => {
return <table className={'my-table'}>
<thead>
<tr>
<th>名称</th>
<th>负责人</th>
</tr>
</thead>
<tbody>
{
list.map(project => <tr key={project.id}>
<td>{project.name}</td>
<td>{users.find(user => user.id === project.personId)?.name || '未知'}</td>
{/*{?.name表示前面的表达式的内容为真时显示name}*/}
</tr>)
}
</tbody>
</table>
}
searh-panel.jsx
import React from "react";
import {useEffect, useState} from "react";
export const SearchPanel = ({param,setParam,users}) => {
return <form action="">
<div>
{/*{setParam(Object.assign({},param,{name:evt.target.value}))}*/}
<input type="text" value={param.name} onChange={evt => setParam({
...param,
name: evt.target.value
})
}/>
<select value={param.personId} onChange={evt => setParam({
...param,
personId: evt.target.value
})}>
<option value={''}>负责人</option>
{
users.map(user => <option value={user.id} key={user.id}>{user.name}</option>)
}
</select>
</div>
</form>
}
App.tsx:
import React from 'react';
import './App.css';
import {ProjectListScreen} from "./screens/project-list";
function App() {
return (
<div className="App">
<ProjectListScreen/>
</div>
);
}
export default App;