根据本人需要,目前只记录React18+TS4,Vue3+TS4可参考课程
后续笔记暂且在本地未整理上传,需要者可私信
“*标题”代表基础知识回顾
目录
基础准备
项目展示
软件说明
版本说明
编辑器及插件说明
浏览器及插件说明
TS4安装及入门
React18安装及入门
初始化工程与整体架构
A.后端接口文档说明及在线数据访问
B.本地接口启动及数据访问
脚手架安装及第三方模块安装与配置
脚手架安装
第三方模块安装
用编辑器打开初始代码
封装axios
拷贝全局样式和图片
创建项目页面
架构项目路由系统及对应页面
配置路由
测试
二级路由
扩展meta元信息接口与全局守卫
扩展meta元信息接口与指定类型
全局守卫组件
权限判定
架构项目状态管理系统
*Redux状态管理
创建状态管理的模块users、 signs、news、checks
配置数据持久化功能并测试后端接口
使用redux-persist模块进行持久化
处理useSelector和useDispatch
调用登录接口和更新token接口
登录界面和首页实现
搭建登录界面
请求头发送token和获取用户信息
拆分首页头部组件和侧边栏组件
1.http://vue.h5ke.top
2.http://react.h5ke.top
数据仅为测试使用,可能会被重置,
React是用于构建用户界面的JavaScript库,起源于Facebook。
vue是轻量级框架,起源于Google
全球趋势肯定是React使用的多一些,毕竟是大公司研发的,有保障,有排面。但在国内的话,其实Vue和React是不相上下的,基本上是两足鼎立的趋势,毕竟Vue使用起来更简单,且中文社区也比较好。
目前在一线公司和一些高级团队中都开始采用Vue+TS或React+TS的开发形式,也慢慢成为了未来的趋势。
React框架:18.2.03.
TypeScript:4.7.44.
nodejs:16.13.1
VSCode编辑器,可官方直接下载(下载最新版或更新到最新版)
插件:
1.VueVSCodeSnippets
2.VueLanguageFeatures(Volar)
3.TypeScriptVuePlugin(Volar)
4.ES7+React/Redux/React-Nativesnippets
Redux应用数据流框架
React Native 将原生开发的最佳部分与 React 相结合
Chrome浏览器,可官方直接下载(下载最新版或更新到最新版)
插件:
1.Vue.jsdevtools
2.ReactDeveloperTools
3.ReduxDevTools
4.TalendAPITester
Talend API Tester是一款Chrome浏览器上交互和调试REST、SOAP和HTTP接口的客户端插件,类似于Postman。
Talend API Tester插件 API测试工具
数据库采用mongodb3.6的版本,robo3t可视化工具
MongoDB数据库安装时不动怎么办?MongoDB数据库安装教程 - 优草派
mongodb安装好后,可以把软件写入到全局环境变量中,这样就可以在全局地址下进行访问了,操作流程如下:
找到安装路径:C:\Program Files\MongoDB\Server\3.6\bin\
此电脑->属性->高级系统设置->环境变量->系统变量->Path
把第一步中的地址,添加到Path中,就可以设置全局成功
解压压缩包app-server,并执行npm install
后端mvc架构:
包含两步:第一步启动数据库,第二个启动后端服务。然后就可以测试接口了。首先先注册两个测试账号,接口调用如下:
```shell
# request POST
http://localhost:3000/users/register
```
```json
// response
{"errcode":0}
```
看到`{"errcode":0}`就表示注册账号成功,会有两个账号数据,即:黄蓉和洪七公。
再进行登录接口测试即可。
```shell
# request POST { "email":"[email protected]", "pass":"huangrong" }
http://localhost:3000/users/login
```
```json
// response
{"errcode":0,"errmsg":"ok","token":"..."}
```
测试接口: http://localhost:3000/users/register
刷新
facebook出了 基于webpack+ES6创建的create-react-app命令,用于react项目开发环境的构建,也是用 React 创建新的单页应用的最佳方式。
安装Node >= 14.0.0 和 npm >= 5.6。
# 安装命令 npx create-react-app my-app cd my-app npm start
主要开发代码在src目录下。App.js为根组件,index.js为入口模块,index.css为全局样式文件。
安装命令:
npx create-react-app 项目名称 --template typescript
axios sass antd ant-design/icons react-router-dom
axios样式预编译sass ant-design/icons的图标,路由
redux react-redux redux-persist @reduxjs/toolkit
状态管理redux,持久化redux-persist,RTK
安装命令:
npm i axios sass antd @ant-design/icons react-router-dom redux react-redux redux-persist @reduxjs/toolkit
React + Ts项目搭建_react+ts项目搭建_iam671的博客-CSDN博客
react项目中引入typescript_2422400672的博客-CSDN博客_react 引入typescript
命令:
项目文件夹中:code .
调整:
引用模块时import后面加上{}和不加{}的区别_Time-Traveler的博客-CSDN博客
import axios from 'axios'
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
const instance = axios.create({
baseURL: 'http://localhost:3000/',
timeout: 5000
});
instance.interceptors.request.use(function (config) {
return config;
}, function (error) {
return Promise.reject(error);
});
instance.interceptors.response.use(function (response) {
return response;
}, function (error) {
return Promise.reject(error);
});
interface Data {
[index: string]: unknown
}
interface Http {
get: (url: string, data?: Data, config?: AxiosRequestConfig) => Promise
post: (url: string, data?: Data, config?: AxiosRequestConfig) => Promise
put: (url: string, data?: Data, config?: AxiosRequestConfig) => Promise
patch: (url: string, data?: Data, config?: AxiosRequestConfig) => Promise
delete: (url: string, data?: Data, config?: AxiosRequestConfig) => Promise
}
const http: Http = {
get(url, data, config){
return instance.get(url, {
params: data,
...config
})
},
post(url, data, config){
return instance.post(url, data, config)
},
put(url, data, config){
return instance.put(url, data, config)
},
patch(url, data, config){
return instance.patch(url, data, config)
},
delete(url, data, config){
return instance.delete(url, {
data,
...config
})
}
}
export default http;
//输入rfc 快捷创建初始结构,react from react
import React from 'react'
import styles from './Login.module.scss'
export default function Home() {
return (
Login
)
}
解决Cannot find module ‘./index.module.scss‘ or its corresponding type declarations.ts(2307)_不吃萝卜不吃菜的博客-CSDN博客
import React,{lazy} from "react";
import { createBrowserRouter } from "react-router-dom";
//指定类型
import type {RouteObject} from "react-router-dom";
//通过懒加载映射Home
const Home=lazy(()=>import('../views/Home/Home'))
const Sign = lazy(()=> import('../views/Sign/Sign'))
const Exception = lazy(()=> import('../views/Exception/Exception'))
const Apply = lazy(()=> import('../views/Apply/Apply'))
const Check = lazy(()=> import('../views/Check/Check'))
const Login = lazy(()=> import('../views/Login/Login'))
//创建路由表
const routes:RouteObject[]=[
{
//根路径
path:'/',
//页面模块
element: React.createElement(Home),
children: [
{
path: 'sign',
element: React.createElement(Sign),
},
{
path: 'exception',
element: React.createElement(Exception),
},
{
path: 'apply',
element: React.createElement(Apply),
},
{
path: 'check',
element: React.createElement(Check),
}
]
},
{
path: '/login',
element: React.createElement(Login)
}
];
//创建router对象
const router=createBrowserRouter(routes);
//对外路由表
export default router;
端口3000改成8080
npm start
ctrl+c 终止运行
//输入rfc 快捷创建初始结构,react from react
import React from 'react'
import styles from './Home.module.scss'
import { Outlet } from 'react-router-dom'
export default function Home() {
return (
Home
)
}
一般情况下,不同的路由获取到的信息是不一样的,可以通过自定义元信息来完成操作。
//index.ts
//引入图标
import {
CopyOutlined,
CalendarOutlined,
WarningOutlined,
FileAddOutlined,
ScheduleOutlined,
} from '@ant-design/icons'
//扩展RouteObject
declare module 'react-router' {
interface IndexRouteObject {
meta?: {
menu?: boolean
title?: string
icon?: React.ReactNode
auth?: boolean
}
}
interface NonIndexRouteObject {
meta?: {
menu?: boolean
title?: string
icon?: React.ReactNode
auth?: boolean
}
}
}
export const routes: RouteObject[] = [
{
path: '/',
element: React.createElement(BeforeEach, null, React.createElement(Home)),
meta: {
menu: true,
title: '考勤管理',
icon: React.createElement(CopyOutlined),
auth: true
},
children: [
{
path: 'sign',
element: React.createElement(Sign),
meta: {
menu: true,
title: '在线打卡签到',
icon: React.createElement(CalendarOutlined),
auth: true
}
},
{
path: 'exception',
element: React.createElement(Exception),
meta: {
menu: true,
title: '异常考勤查询',
icon: React.createElement(WarningOutlined),
auth: true,
}
},
{
path: 'apply',
element: React.createElement(Apply),
meta: {
menu: true,
title: '添加考勤审批',
icon: React.createElement(FileAddOutlined),
auth: true,
}
},
{
path: 'check',
element: React.createElement(Check),
meta: {
menu: true,
title: '我的考勤审批',
icon: React.createElement(ScheduleOutlined),
auth: true,
}
}
]
},
{
path: '/login',
element: React.createElement(BeforeEach, null, React.createElement(Login))
}
];
图标 Icon - Ant Design
引入图标,以组件方式调用React.ReactNode(React中),vue是string,
auth: true,根据是否有权限进行拦截
//index.ts
//懒加载
const BeforeEach = lazy(()=> import('../components/BeforeEach/BeforeEach'))
//给Home和Login这两大部分套上全局守卫BeforeEach
//提供并创建路由表
export const routes:RouteObject[]=[
{
//根路径
path:'/',
//页面模块,属性暂定null,子项为Home
element: React.createElement(BeforeEach,null,React.createElement(Home)),
children: [
...
},
{
path: '/login',
element: React.createElement(BeforeEach,null,React.createElement(Login))
}
];
解决:在主模块中加入suspense,以配合lazy
//index.tsx
import React,{Suspense} from 'react';
...
root.render(
);
Redux就像Vue中的Vuex或Pinia是一样的,专门处理状态管理的。
只不过Redux比较独立,可以跟很多框架结合使用,不过主要还是跟React配合比较好,也是最常见的React状态管理的库。
State:用于存储共享数据
Reducer:用于修改state数据的方法
Middleware:用于扩展一些插件来完成异步的操作
Dispatch:用于触发Reducer或Middleware
因为Redux是一个独立的库,所以和React结合还是不够方便,因此就诞生了react-redux这个库, 第三方模块react-redux
来简化对Redux的使用,属于Redux的一个辅助模块。
useSelector,useDispatch都是react-redux库提供的use函数,可以获取共享状态以及修改共享状态。
Redux在使用上还是有很多不方便的地方,所以提供了Redux-Toolkit(RTK)这个模块,通过这么模块可以更方便的处理Redux的操作,下面列举一些RTK的好处:
可以自动跟redux devtools结合,不需要再下载模块进行生效
数据不需要再通过返回值进行修改,像Vue一样可以直接修改
内置了 redux-thunk 这个异步插件
代码风格更好,采用选项式编写程序
创建文件夹,为了不报错并加载为模块(export{}),其中index.ts为主模块
//users.ts
import http from "../../utils/http";
import { createSlice,createAsyncThunk} from "@reduxjs/toolkit";
import type { PayloadAction } from "@reduxjs/toolkit/dist/createAction";
import http from "../../utils/http";
//指定类型,首字母大写
type Token=string;
type Infos={
[index:string]:unknown
}
type UsersState={
token:Token
infos:Infos
}
//账号和密码
type Login={
email:string
pass:string
}
//参数:'users/loginAction'命名空间,异步方法;
export const loginAction=createAsyncThunk('users/loginAction',async(payload:Login)=>{
//调用封装好的axios,参数:接口。调用
const ret=await http.post('/users/login',payload)
return ret;
})
//获取用户信息
export const infosAction=createAsyncThunk('users/infosAction',async()=>{
const ret=await http.get('/users/infos')
return ret;
})
const usersSlice=createSlice({
//命名空间
name:'users',
//断言共享状态
initialState:{
token:'',
infos:{}
}as UsersState,
//同步方法
reducers:{
updateToken(state,action:PayloadAction){
state.token=action.payload;
},
updateInfos(state,action:PayloadAction){
state.infos=action.payload;
},
clearToken(state){
state.token='';
}
}
})
//将方法结构出来,提供给外部使用
export const {updateInfos,updateToken,clearToken}=usersSlice.actions
export default usersSlice.reducers;
import { configureStore } from "@reduxjs/toolkit/dist/configureStore";
import { useReducer } from "react";
//index.ts
import usersReducer from './modules/users'
const store=configureStore({
reducer:{
users:useReducer
}
})
export default store;
配置主模块,让状态管理生效
...
import { Provider } from 'react-redux';
import store from './store'
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
);
redux-persist模块是对状态管理进行持久化处理的,默认数据是不会被保存下来的,需要长期存储改变的共享数据就需要使用持久化模块。基本配置参考RTK官网即可。
通过本地token
import { configureStore } from "@reduxjs/toolkit/dist/configureStore";
import { useReducer } from "react";
//index.ts
import usersReducer from './modules/users'
//引入
import {
persistStore,
persistReducer,
// FLUSH,
// REHYDRATE,
// PAUSE,
// PERSIST,
// PURGE,
// REGISTER,
} from 'redux-persist'
import storage from 'redux-persist/lib/storage'
//配置
const persistConfig = {
key: 'root',
version: 1,
storage,
//白名单
whitelist: ['token']
}
const store=configureStore({
reducer:{
users:persistReducer(persistConfig, usersReducer)
},
//复制官网的中间件
middleware: (getDefaultMiddleware) =>
//为了持久化默认调用了一些任务,为序列化产生了冲突
// serializableCheck: {
// ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
// },
//序列化做成false
serializableCheck: false
}),
})
//配置持久化
persistStore(store)
export default store;
//index.ts
...
import { useDispatch } from 'react-redux'
...
export type RootState = ReturnType
export type AppDispatch = typeof store.dispatch
export const useAppDispatch: () => AppDispatch = useDispatch
...
//Login.tsx
import React from 'react'
import styles from './Login.module.scss'
import { Button, message } from 'antd'
import { useSelector } from 'react-redux'
import { useAppDispatch } from '../../store'
import type { RootState } from '../../store'
import { loginAction, updateToken } from '../../store/modules/users'
export default function Login() {
const token = useSelector((state: RootState)=> state.users.token)
const dispatch = useAppDispatch()
const handleLogin = () => {
dispatch(loginAction({ email: '[email protected]', pass: 'huangrong' })).then((action)=>{
const {errcode, token} = (action.payload as {[index: string]: unknown}).data as {[index: string]: unknown}
if( errcode === 0 && typeof token === 'string' ){
dispatch(updateToken(token))
message.success('登录成功');
}
else{
message.error('登录失败');
}
})
}
return (
Login
{ token }
)
}
1.当持久化后,会推断不出来类型
2. 那么写错时就不会提醒
3.观察users推断出来的是什么类型
4.断言类型
//index.ts
import type { Reducer, AnyAction } from '@reduxjs/toolkit'
import usersReducer from './modules/users'
import type { UsersState } from './modules/users'
import type { PersistPartial } from 'redux-persist/es/persistReducer'
...
const store=configureStore({
reducer:{
users:persistReducer(persistConfig, usersReducer) as Reducer
}
...
})
...
export type RootState = ReturnType
...
//Login.module.scss
.login {
width: 100vw;
height: 100vh;
background: url('../../assets/images/login-bg.svg') no-repeat center 110px;
background-size: 100%;
.header {
height: 44px;
line-height: 44px;
display: flex;
justify-content: center;
align-items: center;
font-size: 34px;
padding-top: 100px;
.header-logo {
.icon-react,
.icon-icon-test,
.icon-typescript {
margin-right: 5px;
font-size: inherit;
}
.icon-react {
color: #61dafb;
}
.icon-icon-test {
color: #deb887;
}
.icon-typescript {
color: blue;
}
}
.header-title {
margin-left: 30px;
font-weight: 700;
font-size: 30px;
}
}
.desc {
text-align: center;
padding-top: 30px;
color: rgba(0, 0, 0, 0.45);
font-size: 16px;
}
.main {
width: 500px;
margin: 0 auto;
padding-top: 50px;
}
.users{
width: 500px;
margin: 60px auto;
color: rgba(0,0,0,.65);
h3{
font-size: 16px;
}
p{
margin: 20px;
}
}
}
Ant Design表单组件: