使用 React,实际开发中常用框架
- UI 框架 antd.design
- 路由管理 (SPA ) react-router-dom
- 状态管理 redux,mobx,dva
UI 框架 antd.design
-
npm install antd // (不带版本,安装最新版本)
-
npm install react-app-rewired customize-cra // 默认配置进行自定义
/* package.json */ "scripts": { - "start": "react-scripts start", + "start": "react-app-rewired start", - "build": "react-scripts build", + "build": "react-app-rewired build", - "test": "react-scripts test", + "test": "react-app-rewired test", }
-
项目根目录创建一个
config-overrides.js
用于修改默认配置。 -
npm install babel-plugin-import // 按需加载 antd 组件样式
-
替换 moment.js 使用 day.js
-
npm install antd-dayjs-webpack-plugin dayjs
-
使用到的完整配置
const { override, fixBabelImports, addLessLoader, addWebpackPlugin, } = require("customize-cra"); const AntdDayjsWebpackPlugin = require("antd-dayjs-webpack-plugin"); module.exports = override( // antd 组件库按需加载 fixBabelImports("import", { libraryName: "antd", libraryDirectory: "es", style: "true", }), // antd 时间组件 替换 moment.js 使用 day.js addWebpackPlugin(new AntdDayjsWebpackPlugin()), // 使用 less 样式预处理,自定义主题样式 addLessLoader({ javascriptEnabled: true, modifyVars: { "@primary-color": "#1DA57A" }, }) );
-
-
npm start 查看效果
单页面应用 SPA (single page application)
- 集成 react-router-dom
- npm install react-router-dom
集成 react-router-dom
-
react-router-dom 常用组件、API
-
BrowserRouter、HashRouter 包裹所有路由
- HashRouter 路径上添加 /#/
- BrowserRouter 构建于 H5 History API,更方便操作路由跳转
-
Switch 区分BrowserRouter、HashRouter 包裹路由跳转
-
-
Route 挂载不同的路由显示界面
-
Link 用于跳转,类似 a 标签
-
代码方式跳转
import { useHistory } from "react-router-dom"; history.push("/home");
-
-
调整目录结构
-
创建 components 目录,存放组件
- 创建 ClassComponent、FunctionComponent 文件夹,移动至 components 目录
-
创建 pages 目录,存放不同页面
-
创建 component、home 页面组件
-
home.jsx
const Home = () => { return <div>Home</div>; }; export default Home;
-
component.jsx
import { Divider } from "antd"; import ClassComponent from "../components/ClassComponent"; import FunctionComponent from "../components/FunctionComponent"; const Component = () => { return ( <div> <ClassComponent title="Class 组件" /> <Divider /> <FunctionComponent title="Function 组件" /> </div> ); }; export default Component;
-
-
-
修改 App.js,使用 antd 组件进行界面布局
import React from "react"; import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom"; import { Layout, Menu } from "antd"; import Home from "./pages/home"; import Component from "./pages/component"; import "./App.css"; const { Header, Content, Footer } = Layout; const App = () => { return ( <div classNam="App"> <Router> <Layout className="layout"> <Header> <Menu theme="dark" mode="horizontal" defaultSelectedKeys={["home"]} style={{ lineHeight: "64px" }} > <Menu.Item key="home"> <Link to="/">首页</Link> </Menu.Item> <Menu.Item key="component"> <Link to="/cc">组件</Link> </Menu.Item> </Menu> </Header> <Content style={{ padding: "0 50px" }}> <div style={{ background: "#fff", padding: 24, minHeight: "88vh" }}> <Switch> <Route path="/cc"> <Component /> </Route> <Route path="/"> <Home /> </Route> </Switch> </div> </Content> <Footer style={{ textAlign: "center" }}> 全栈技术部 ©2021 Created by 桃花 </Footer> </Layout> </Router> </div> ); }; export default App;
运行效果
router 参数
-
传递参数
- 通过定义 <Route path="/path/:id"></Route>
- Link 传递
<Link to="/path/xxxx">
-
获取参数
- 使用 withRouter 构造 HOC,从 props 中可以拿到传递参数
- 代码方式
- 使用 withRouter 构造 HOC,从 props 中可以拿到传递参数
import { useParams } from "react-router-dom"; let { id } = useParams();
- 使用 withRouter 构造 HOC,从 props 中可以拿到传递参数
更多参考 https://reactrouter.com/web/guides/quick-start
dva 状态管理
为什么使用 dva 来进行状态管理?
- dva 对 redux 进行了封装,暴露简单易用 API(同步、异步)
- 后面结合 umi.js + antd.design + antd.dedign-pro 开箱即用中台前端/设计解决方案
dva 使用
栗子: 使用 dva 构建一个用户界面,进行用户管理
安装 dva 依赖
npm install dva
修改 index.js 使用 dva 管理状态
// import React from "react";
// import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import dva from "dva";
import { createBrowserHistory as createHistory } from "history";
import userModel from "./models/user";
const app = dva({
history: createHistory(),
onError: (err, dispatch) => {
console.log("onError ===> ", err, dispatch);
},
});
app.model(userModel);
app.router(App);
app.start(document.getElementById("root"));
// ReactDOM.render(
// <React.StrictMode>
// <App />
// </React.StrictMode>,
// document.getElementById("root")
// );
reportWebVitals();
创建 user model,管理 user 状态
-
models/user.js
const userModel = { // 名称空间 namespace: "user", // 初始化状态数据 state: { userList: [ { id: 1, name: "桃花", }, ], }, effect: { // 异步请求。可以是网络请求,延时操作 *submit(action, { put, call, select }) {}, }, reducers: { // 添加用户 add(state, { payload: { user } }) { let { userList = [] } = state; const temp = userList.concat(); temp.push({ id: userList.length + 1, ...user }); return { ...state, userList: temp, }; }, // 删除用户 delete(state, { payload: id }) { let { userList = [] } = state; return { ...state, userList: userList.filter((item) => item.id !== id), }; }, }, // 监听路由变化 subscriptions: { setup({ dispatch, history }) { // history.listen(location => {}); }, }, }; export default userModel;
-
namespace 命名空间,可以根据区分不同业务数据,使 dispatch 触发不同类型 action (redux)
dispatch({ type: "user/add", payload: { /* 数据传递*/ } })
-
effect 触发异步动作,同 redux-saga
-
reducers 同步动作
-
subscriptions 可以监听路由变化,获取参数,进行鉴权操作
-
构建 user 界面
-
在 pages 目录下创建 user.jsx
-
使用 antd 组件进行 UI 界面布局
-
使用 connect 进行数据订阅绑定
import { connect } from "dva"; import { Form, Input, Button, Table } from "antd"; const User = ({ user, dispatch }) => { const { userList } = user; const [form] = Form.useForm(); console.log(user); const onFinish = (values) => { dispatch({ type: "user/add", payload: { user: values, }, }); form.resetFields(); }; const onDelete = (id) => { dispatch({ type: "user/delete", payload: id, }); }; const columns = [ { title: "ID", dataIndex: "id", key: "id", }, { title: "姓名", dataIndex: "name", key: "name", }, { title: "操作", key: "action", render: (text, record) => ( <Button size="middle" onClick={() => onDelete(record.id)}> 删除 </Button> ), }, ]; return ( <div> <Form name="user_form" form={form} layout="inline" onFinish={onFinish}> <Form.Item name="name" rules={[{ required: true, message: "Please input your name!" }]} > <Input placeholder="Name" /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit"> 添加 </Button> </Form.Item> </Form> <Table style={{ width: 500, marginTop: 10 }} rowKey={(record) => record.id} columns={columns} dataSource={userList} /> </div> ); }; export default connect(({ user }) => ({ user, }))(User);
关注公众号 「全栈技术部」
,不断学习更多有趣的技术知识。