一直用的Vue,有个项目要用react,负责人说跟Vue3.0很像,问多久能上手?信心满满,说2天吧,于是开启了打脸心酸历程。本篇记录了用 react17+ts+antd+ReactRouteDom6 搭建项目的历程,可谓处处碰壁!
1.安装和初始化
1.创建项目
请确保电脑上已经安装了最新版的 yarn 或者 npm。 我电脑yarn、npm版本如下:
使用 yarn 创建 cra-template-typescript 项目。
npx create-react-app antd-demo-ts --template typescript
or use yarn...
yarn create react-app antd-demo-ts --template typescript
然后我们进入项目并启动。
cd antd-demo-ts
yarn start
此时浏览器会访问 http://localhost:3000/ ,看到 Welcome to React
的界面就算成功了。
2.引入 antd
项目目录下运行:
$ yarn add antd
修改 src/App.tsx
,引入 antd 的按钮组件。
import React, { FC } from 'react';
import { Button } from 'antd';
import './App.css';
const App: FC = () => (
<div className="App">
<Button type="primary">Button</Button>
</div>
);
export default App;
修改 src/App.css
,在文件顶部引入 antd 的样式。
@import '~antd/dist/antd.css';
重新启动yarn start
或npm run start
,出现以下界面为引入成功:
2.配置样式文件
React
脚手架自身支持.css, .Scss, .Sass
,如果想使用less
,需要自己添加对less
的配置。以下介绍styled-components
css modules
Sass
less
四种编写样式的使用。
1.styled-components的使用
styled-components
官方文档地址: www.styled-components.com/
styled-components
中文文档地址:github.com/hengg/style…
styled-components
是一个React
的第三方库,是CSS in JS
的优秀实践。styled-components
是在js中去编写css,创建后就是一个正常的React
组件,并且可以附加样式给当前组件,这种设计跟react
相当的般配。
1.安装styled-components
npm install --save styled-components
2.vscode语法提示高亮
vscode扩展商店搜索 vscode-styled-components
,直接安装。
上面这个这段代码就可以把WrapStyle
当做一个正常的组件导入react组件中使用。
2.引入并使用css modules
关于css模块化,想了解更多的话可以看下梳理 CSS 模块化,通过与sass,less的对比,比较清晰的认知css modules
是什么。阮一峰的网络日志 CSS Modules 用法教程中讲述了css modules
使用规则。
css modules
的好处是:
- 样式私有化
- 避免被其他样式文件污染
- 可复用
- 在
src
目录下新建style/common.module.css
文件,请注意,必须是*.module.css
!!! 输入import ""
vscode提示可以看出配置了哪些后缀文件。
.red{color: red;}
- 打开APP.tsx 文件新增以下代码 :
import React, { FC } from "react";
import "./App.css";
import styles from "./style/common.module.css";
const App: FC = () => (
<div className="App">
<h1 className={styles.red}>red</h1>
</div>
);
export default App;
3.安装Sass和node-sass并使用Sass
- 安装Sass和node-sass
npm install node-sass
...or use yarn
yarn add node-sass
- 报错node-sass为 7.0.0版本,与^4.0.0 || ^5.0.0不兼容:
./src/style/common.module.scss (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-7-1!./node_modules/postcss-loader/src??postcss!./node_modules/resolve-url-loader??ref--5-oneOf-7-3!./node_modules/sass-loader/dist/cjs.js??ref--5-oneOf-7-4!./src/style/common.module.scss)
Node Sass version 7.0.0 is incompatible with ^4.0.0 || ^5.0.0.
- 首先先卸载node-sass为5.0.0版本
npm uninstall node-sass
...or use yarn
yarn remove node-sass
- 卸载后安装4.0.0版本(5.0.0版本之前的)
npm install node-sass@4.14.1
...or use yarn
yarn add node-sass@4.14.1
将上述 style/common.module.css
文件重命名为common.module.scss
,App.tsx
引入改为import styles from "./style/common.module.scss";
重启后依然有效。
4.安装 Less 和 Less-loader并使用Less
1. 安装 Less 和 Less-loader
npm i less less-loader
...or use yarn
yarn add less less-loader
2. 打开隐藏的webpack
配置文件
- 打开隐藏的
webpack
配置文件
npm run eject
...or use yarn
yarn eject
- 报错,问题是脚手架添加
.gitgnore
文件,但是却没有本地仓库
This git repository has untracked files or uncommitted changes:
package.json
D public/logo192.png
D public/logo512.png
D public/manifest.json
D public/robots.txt
M src/App.css
D src/App.test.tsx
M src/App.tsx
D src/index.css
M src/index.tsx
D src/logo.svg
D src/reportWebVitals.ts
D src/setupTests.ts
M yarn.lock
package-lock.json
src/style/
Remove untracked files, stash or commit any changes, and try again.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
- 解决方法,依次执行以下命令:
git init
git add .
git commit -m "Saving before ejecting"
yarn eject
- 项目目录下显示了
webpack
配置文件config
文件夹:
3. webpack中配置Less
打开 config 文件夹,修改 webpack.config.js,可以搜索下Sass
,less
与Sass
配置基本一致,可以仿照sass配置去理解。
添加后缀匹配:
- 搜索
cssRegex
,找到后添加两行代码:
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
- 修改 getStyleLoaders 函数,添加代码
{
loader: require.resolve("less-loader"),
options: lessOptions,
},
- 添加以下代码在
test: sassModuleRegex,
下面:
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
},
"less-loader"
),
sideEffects: true,
},
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
getLocalIdent: getCSSModuleLocalIdent,
},
},
"less-loader"
),
},
4. 重启后报错:less-loader安装的版本过高到导致,需要安装6以下版本
Failed to compile.
./src/App.css (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-4-1!./node_modules/less-loader/dist/cjs.js!./node_modules/postcss-loader/src??postcss!./src/App.css)
TypeError: this.getOptions is not a function
解决方法,依次执行命令:
npm uninstall less-loader
npm install less-loader@5.0.0
...or use yarn
yarn remove less-loader
yarn add less-loader@5.0.0
4. 在*.d.ts
中添加第三方库的声明
在react-app-env.d.ts
中添加第三方库的声明,不然在.tsx
文件中引入less
文件会报错:
declare module "*.module.less" {
const classes: { readonly [key: string]: string };
export default classes;
}
将上述 style/common.module.css
文件重命名为common.module.less
,App.tsx
引入改为import styles from "./style/common.module.less";
重启后依然有效。
5.react引入less全局样式文件
- 安装
style-resources-loader
插件,插件地址>>
style-resources-loader
是一个用于webpack
的 CSS 处理器资源加载器,它将你的样式资源(例如变量,mixins)注入到多个导入的CSS, sass, scss, less, stylus
模块中。 运行命令如下:
npm install --save-dev style-resources-loader
...or use yarn
yarn add --save-dev style-resources-loader
2.在webpack中配置less全局样式文件:
修改 webpack.config.js
中 test: lessRegex,
与test: lessModuleRegex
部分如下:
请注意,path.resolve(__dirname,"../src/style/globle.module.less"改为你放置公共样式文件的地址
{
test: lessRegex,
exclude: cssModuleRegex,
use: [
...getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
},
"less-loader"
),
{
loader: "style-resources-loader",
options: {
patterns: path.resolve(
__dirname,
"../src/style/globle.module.less"
),
},
},
],
sideEffects: true,
},
{
test: lessModuleRegex,
use: [
...getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
getLocalIdent: getCSSModuleLocalIdent,
},
},
"less-loader"
),
{
loader: "style-resources-loader",
options: {
patterns: path.resolve(
__dirname,
"../src/style/globle.module.less"
),
},
},
],
},
重启项目,现在 "../src/style/globle.module.less"
中定义的less就是全局的了。
3.引入路由并使用
1. 安装react-router-dom
React Router
为React-Router dom
和React-Router native
提供了所有的核心功能。React-Router-dom
包包含了在web应用中使用React Router
的绑定,所以我们只安装react-router-dom
即可:
npm install react-router-dom
...or use yarn
yarn add react-router-dom
2.引入路由并使,心酸百度路:
此处要说一下,这里百度的要哭了,看了所有的文档,都写的<Route path="" component=""></Route>
,然而一直报错,但都没有找到我需要的。。。。最后问了一个同事,他说现在的写法是<Route path="/" element={<Compoent/>}></Route>
。鬼知道我为什么要用一天时间百度路由这个东西。
- 错误写法!!!:
TypeScript error in ....
Type '{ path: string; component: Element; }' is not assignable to type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.
Property 'component' does not exist on type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.
- 正确写法!!!: App.tsx
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import PageA from "./pages/pageA";
import PageB from "./pages/pageB";
const Root = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<PageA />}></Route>
<Route path="/pageA" element={<PageA />}></Route>
<Route path="/pageB" element={<PageB />}></Route>
</Routes>
</BrowserRouter>
);
};
export default Root;
PageA.tsx:
import React from "react";
import { Link } from "react-router-dom";
class PageA extends React.Component {
render() {
return (
<div>
<div>PageA</div>
<Link to="/pageB">跳转pageB</Link>
</div>
);
}
}
export default PageA;
PageB.tsx:
import React from "react";
import { Link } from "react-router-dom";
class PageB extends React.Component {
render() {
return (
<div>
<div>pageB</div>
<Link to="/pageA">跳转pageA</Link>
</div>
);
}
}
export default PageB;
效果如下:
4.axios封装:
1. 安装axios
npm install axios
or use yarn...
yarn add axios
2.封装axios:
之前写vue3+ts时有写过,直接拿过来修改下Ui组件就可以,再贴一次代码:
import axios, {
AxiosRequestConfig,
AxiosRequestHeaders,
AxiosResponse,
} from "axios";
import { message } from "antd";
//返回数据规则
export interface IResponseData<T> {
status?: number;
msg?: string;
img?: string;
data?: T;
code: number;
captchaOnOff?: boolean;
uuid?: string;
token?: string;
}
const state = {
ok: 200, //请求成功状态码
};
//请求默认配置规则
type TOption = {
baseURL: string;
timeout: number;
};
//默认配置
const config = {
baseURL: "/api",
timeout: 30 * 1000,
withCredentials: true,
};
const whiteUrl = ["/captchaImage", "/login"];
class Http {
service: any;
constructor(config: TOption) {
//实例化请求配置
this.service = axios.create(config);
//请求拦截
this.service.interceptors.request.use(
(config: AxiosRequestConfig) => {
let stateToken = localStorage.getItem("token") as string;
if (config.url && !whiteUrl.includes(config.url) && stateToken) {
(config.headers as AxiosRequestHeaders).authorization = stateToken;
}
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
//响应拦截
this.service.interceptors.response.use(
(response: AxiosResponse) => {
const data = response.data;
const { code } = data;
if (!code) {
//如果没有返回状态码,直接返回数据,针对于返回数据为blob类型
return response;
} else if (code !== state["ok"]) {
message.error(data.msg || "请求异常");
return Promise.reject(data);
}
return response.data;
},
(error: any) => {
message.error("请求失败");
return Promise.reject(error);
}
);
}
get<T>(url: string, params?: object, data = {}): Promise<IResponseData<T>> {
return this.service.get(url, { params, ...data });
}
post<T>(url: string, params?: object, data = {}): Promise<IResponseData<T>> {
return this.service.post(url, params, data);
}
put<T>(url: string, params?: object, data = {}): Promise<IResponseData<T>> {
return this.service.put(url, params, data);
}
delete<T>(
url: string,
params?: object,
data = {}
): Promise<IResponseData<T>> {
return this.service.delete(url, { params, ...data });
}
}
export default new Http(config);
3.使用:
随便找了个掘金的请求地址,在App.tsx中测试下:
import React from "react";
import http from "./utils/http";
const Root = () => {
http.post("https://mcs.snssdk.com/v1/list",{ /*请求的参数*/},{/*添加默认请求配置如header,baseUrl等*/}).then((res: any) => {
console.log(res);
}).catch((err: any) => {
console.log(err);
});
return <h1>主页</h1>;
};
export default Root;
其他
之前有写从零搭建后台系统(Vue3.0+ElementPlus+TS+Vite),想把后续过程记录下来,暂时还没时间继续写完。
以前喜欢写笔记,一本一本,写完就扔了,掘金给我提供了一种新的记笔记的方式,O(∩_∩)O哈哈~