初始化脚手架结构
public/
favicon.ico
index.html
manifest.json
src/
assets/
somponents/
utils/
views/
App.js
index.js
修改说明
1 把 app.js(改小写), 放在 assets 中
2 把 index.css 的内容接剪切到 app.css 中 (然后在入口文件中引入合并后的 css文件即可)
3 然后 App.js 中就不需要引入 App的 css文件了
4 把 logo.svg, 也扔到 asstes 中
5 把 App.js 中的 reportWebVitals 相关删除
6 把 scripts/manifest.json 俩个 png对象的 src删除掉
项目环境常用配置 (需要详细完善, 还有很多不成功)
1 改端口
---------------------------------------------------------------------------
1 script/start.js
位置P48: const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
2 自定义配置文件 (根目录: react.config.js)
module.exports = {
devServer: {
props: 9000
}
}
3 在 script/start.js 中 (导入自定义的配置文件)
1 位置: const isInteractive = process.stdout.isTTY; 后面 (P40)
2 添加代码: const reactConfig = require('../react.config')
3 修改端口配置位置的代码
1 const DEFAULT_PORT = parseInt(process.env.PORT, 10) || reactConfig.devServer.port || 3000;
---------------------------------------------------------------------------
2 修改入口文件的名字
---------------------------------------------------------------------------
1 fonfig/paths.js
1 P58, 找到抛出的路径, 对应的: 'src/index' -> 'src/main'
---------------------------------------------------------------------------
3 跨域
---------------------------------------------------------------------------
1 config/webpackDevServer.config.js 中
1 P17: const reactConfig = require('../react.config')
2 P106: proxy: reactConfig.devServer.proxy || proxy,
2 然后就可以在, react.config.js 中, 像Vue中配置跨域一样
devServer: {
port: 9000
proxy: {
'/soso': {
target: 'https://baidu.com',
changeOrigin: true
}
}
},
---------------------------------------------------------------------------
4 支持 @ 路径
---------------------------------------------------------------------------
1 config/webpack.config.js 中
1 P77: const reactConfig = require('../react.config')
2 P336: ...(reactConfig.alias || {
})
2 react.config.js 中
1 const path = require('path')
2 module.exports = {
alias: {
'@': path.resolve(__dirname, './src')}}
---------------------------------------------------------------------------
5 如何支持 Less
---------------------------------------------------------------------------
1 config/webpack.config.js 中
1 P561: ...(reactConfig.module ? (reactConfig.module.rules || []) : [])
2 react.config.js 中
module.exports = {
module: {
rules: [{
test: /\.less/, use: ['less-loader']}]}
}
3 安装
1 npm i less-loader -D
2 npm i less -D
---------------------------------------------------------------------------
5 如何支持 Sass
---------------------------------------------------------------------------
1 安装
1 npm i sass-loader -D
2 npm i sass -D
---------------------------------------------------------------------------
6 如何关闭 ES6 line检测错误
---------------------------------------------------------------------------
复制报错最后面的提示 -> 打开 src/package.json -> 找到 "rules" -> 设置 ("粘贴": 0)
---------------------------------------------------------------------------
7 接到项目的第一时间要搞明白的事
---------------------------------------------------------------------------
1 store 全局状态管理
2 utils 里面调接口的等等
3 react.config.js 项目的配置
4 src/views/index.js 路由配置
5 再看看入口文件 + App.js 文件
---------------------------------------------------------------------------
8 扩展知识
---------------------------------------------------------------------------
1 所有后台管理系统, 必须要有权限管理 (它的做法非常多)
---------------------------------------------------------------------------
布局 layout
1 环境配置
---------------------------------------------------------------------------
1 起步
1 npm i antd -S
2 src/index.js: import 'antd/dist/antd.css'
3 按需使用即可
2 定制主题
1
3 注意
1 出现这个警告: index.js:8 You are using a whole package of antd, please use
https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size.
2 根据提示安装使用这个包
1 npm i babel-plugin-import
2 config/webpack.config.js 中找到 P425
原代码: require.resolve('react-refresh/babel'), 后面跟上下面的代码
+: ["import", {
"libraryName": "antd", "style": true}]
---------------------------------------------------------------------------
2 定义布局组件
---------------------------------------------------------------------------
1 src/components/layout/index.js
2 src/components/index.js
1 import WeiLayout from './layout'
2 export {
WeiLayout}
3 src/App.js
1 import {
WeiLayout} from './components'
2 const A1 = () => {
return(<div className="app"> <WeiLayout/> </div>)}
4 修改样式
1 全局样式 src/assets/app.js
#root{
position: absolute; top: 0; left: 0; right: 0; bottom: 0; overflow: hidden;}
.app {
height: 100%; width: 100%;}
2 组件样式
1 定义样式 src/components/layout/style.scss
1 .wei-layout{
height: 100%; .ant-layout {
height: 100%}}
2 使用样式 src/components/layout/index.js
1 import './style.scss'
2 export default props => {
return (<div className='wei-layout'></div>)}
---------------------------------------------------------------------------
路由
1 起步
---------------------------------------------------------------------------
1 安装
1 npm i react-router-dom -S
2 icon库: npm i @ant-design/icons -S
2 App.js
1 import {
HashRouter} from 'react-router-dom'
2 function App() {
return{
<HashRouter></HashRouter>}}
3 安装代码分割相关模块
1 npm i @loadable/component -S
2 npm i @babel/plugin-syntax-dynamic-import -D
3 npm i @babel/preset-react -D
4 src/views/index.js
1 import loadable from '@loadable/component'
2 导入组件
1 const Home = loadable(()=>import('./home/index.js'))
2 const Redux = loadable(()=>import('./home/Redux'))
3 配置路由
export default [
{
id: 1, txt: '首页管理', path: '/home', component: Home},
{
id: 2, txt: 'redux测试', path: '/redux', component: Redux}
]
5 布局组件中, 设置菜单导航
1 src/components/layout/WSider.js
1 import {
NavLink } from 'react-router-dom'
2 组件视图: <NavLink to="/home"> home </NavLink>
---------------------------------------------------------------------------
导航菜单+路由关联
1 起步
---------------------------------------------------------------------------
1 安装: npm i @ant-design/icons -S
2 使用组件基础, 通常需要引入一下三类内容 (三者相互关联)
1 模块库
2 组件方法
3 视图标签
3 注意
1 有些组件的使用, 不被支持 (警告: 在StrictMode中不推荐使用findDOMNode)
1 解决方式: src/index (入口文件中)
2 这样挂载 App实例: ReactDOM.render(<App />, document.getElementById('root'))
2 同一个路由导航菜单, 被连续点击出现警告的问题
1 解决方式: 老夏说不管, 有兴趣再搞
4 使用组件提升, 通过观察发现
1 一个 <Menu.Item></Menu.Item> 标签, 就是一个小的切换菜单按钮
2 一个 <SubMenu></SubMenu> 标签, 就是一个二级菜单
3 简单的调整为自己喜欢的格式 (个人喜好, 方便后面循环的设置)
---------------------------------------------------------------------------
2 导航菜单 (通过自定义路由配置文件循环渲染)
---------------------------------------------------------------------------
1 src/views/index.js
1 由于有二级菜单, 所以准备用二级路由的方式来控制, 菜单导航的跳转
2 新的自定义路由配置文件格式
import {
AppstoreOutlined, ..} from '@ant-design/icons'
import React from 'react'
const routes = [
{
id: 1,
txt: '首页管理',
icon: <AppstoreOutlined/>,
children: [
{
id: 101, txt: '概括', path: '/home', component: Home},
{
id: 102, txt: '学习', path: '/redux', component: Redux}
]
},
{
id: 2, txt: '客户管理', icon: <XXX/>, children: [{
}, {
}]}
]
2 src/components/layout/WSider.js
1 import routes from '@/views.index'
2 封装渲染导航菜单的方法
1 注意每个二级菜单的 icon 都是不一样的, 我们也要定义在路由配置文件中
const renderNav = () => {
return routes.map(v=>(
<SubMenu key={
v.id} icon={
v.icon} title={
v.txt}>
{
v.children.map(e=>(
<Menu.Item key={
e.id}>
<Link to={
e.path}>{
e.txt}</Link>
</Menu.Item>
))}
</SubMenu>
))
}
3 src/components/layout/WContent.js
1 import routes from '@/views/index';
2 定义渲染标签视图的方法
const renderRoute = () => {
const arr = []
routes.map(v=>{
if (v.children) {
v.children.map(e=> {
arr.push(
<Route key={
e.id} path={
e.path} component={
e.component}/>
)
})
}
})
return arr
}
---------------------------------------------------------------------------
Redux
1 起步
---------------------------------------------------------------------------
1 创建: src/store/index.js
2 安装
npm i redux -S
npm i react-redux -S
npm i redux-thunk -S
npm i axios -S
3 环境配置
1 src/App.js
1 import {
Provider} from 'react-redux'
2 import store from './store/index.js'
3 <Provider store={
store}> 标签, 可当做路由模式的子标签, 包裹住 App.js 的组件视图
4 注意事项
1 redux 中的 useDispatch, 只支持派发同步的action (不支持异步)
2 用到异步 -> 需要安装一个第三方库: redux-thunk
3 如何使用
1 初始化全局状态管理文件: src/store/index.js
import {
applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
const store = createStore(a1, applyMiddleware(thunk))
4 关于 thunk 的原理解析
1 const dispatch = useDispatch() / dispatch(xx)
2 thunk 用于判断 xx, xx=普通对象直接派发, xx不是对象 thunk会阻止派发
3 dispatch(xx) 正常情况 xx不是对象就会报错, 有了 redux-thunk就不会报错了
4 如果 xx 是函数, 就会先调用这个方法
5 由于通过这个调接口, 有时候会有重复的接口, 我们可以把这些 xx 集合到一个文件中方便管理
6 新建目录 actions
---------------------------------------------------------------------------
2 基础配置: src/store/index.js
---------------------------------------------------------------------------
1 引入模块
import {
createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
2 定义数据
const initState = {
msg1: 'hello redux'}
3 定义方法
function a1(state=initState, action) {
let newState = JSON.parse(JSON.stringify(state))
switch (action.type) {
case 'add':
newState.msg1 += 6
break; ...
}
return newState
}
4 相关操作
const store = createStore(a1, applyMiddleware(thunk))
export default store
---------------------------------------------------------------------------
3 单文件组件中, Redux 高阶函数的使用方式
---------------------------------------------------------------------------
1 引入模块
import {
connect} from 'react-redux'
2 定义组件
const R = props => {
}
3 定义方法
function fn1(store) {
return {
xx: store.msg1}
}
function fn2(dispatch) {
return {
hh: ()=>dispatch({
type: 'add', payload: 'hello 2021'})}
}
const ck1 = () => {
props.hh()
}
4 抛出组件
export default connect(fn1, fn2)(R)
---------------------------------------------------------------------------
4 单文件组件中, Redux HOOK的使用方式
---------------------------------------------------------------------------
1 引入模块
import {
useDispatch, useSelector} from 'react-redux'
2 定义组件
const A = props => {
const msg = useSelector(store=>store.msg)
const dispatch = useDispatch()
return ()
}
3 定义方法
1 定义修改全局数据的, 函数事件
const ck1 = () => {
dispatch({
type: 'add', payload: 'hello 2021'})
}
4 抛出组件
export default A
---------------------------------------------------------------------------
5 redux 标准规范写法
---------------------------------------------------------------------------
1 创建全局状态管理文件的, 子模块: src/store/reducers/hh1.js
1 定义数据
const initState = {
msg1: 'hello redux'}
2 定义方法
export default function A(state=initState, action) {
let newState = JSON.parse(JSON.stringify(state))
switch(action.type) {
case 'add':
newState.msg1 += '66'
breack;
default:
}
return newState
}
2 在 src/store/index.js 自定义全局状态管理文件中
1 导入模块
import {
createStore, applyMiddleware, combineReducers} from 'redux'
import home from './reducers/home'
import react from './reducers/react'
2 相关操作
const rootReducer = combineReducers({
home, react})
const store = createStore(rootReducer, applyMiddleware([thunk]))
export default store
3 在单文件组件中使用 redux 数据
1 import {
useDispatch, useSelector} from 'react-redux'
2 获取全局状态, 封装的子模块 home 中的数据
cnost A = props => {
const msg = useSelector(store=>store.home.msg)}
3 调用全局状态方法的时候
1 const dispatch = useDispatch()
2 const ck1 = () => {
dispatch({
type: 'add', payload: 'hello 2021'})}
4 封装以及使用 dispatch 参数对象action相关操作 (若)
1 封装 action 的type 属性: src/store/actionType.js
export default {
ADD: 'ADD', ..}
2 在 src/store/actions/index.js 中
import type from '../actionType.js'
function changeMsg(payload) {
return {
type: type.ADD, payload}
}
export default {
changeMsg}
3 在单文件组件中
import {
changeMsg} from 'src/store/actions/index.js'
dispatch( changeMsg('hello 2021'))
4 在全局状态的子模块中
import type from '../actionType.js'
switch(action.type) {
case type.ADD:
newState.msg1 += '66'
break;
default:
}
5 新建的集中管理文件: src/store/actions
---------------------------------------------------------------------------
请求数据
1 起步
---------------------------------------------------------------------------
1 概念
1 React 推介, 调接口这些数据等都应该是从外部进来的
2 安装
1 npm i axios S
---------------------------------------------------------------------------
2 呵呵
---------------------------------------------------------------------------
1 请求数据的位置: src/store/actions/hh.js ??
---------------------------------------------------------------------------
跨域代理
1 第一种处理方式
---------------------------------------------------------------------------
1 安装
1 npm i http-proxy-middleware -S
2 新建文件: src/setupProxy.js
const {
createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
};
3 配置代理
const {
createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:5000',
changeOrigin: true,
})
)
}
---------------------------------------------------------------------------
2 第二种处理方式
---------------------------------------------------------------------------
上面的, 项目环境常用配置里面
---------------------------------------------------------------------------
3 第三种处理方式
---------------------------------------------------------------------------
---------------------------------------------------------------------------
商品列表页
1 在项目中添加一个商品列表页模块, 需要干的事
---------------------------------------------------------------------------
1 新建组件 -> 在自定义路由配置文件中 -> 添加路由
2 简单修改组件的全局样式 -> src/components/layout/..
---------------------------------------------------------------------------
2 启动老师的 node 数据库
---------------------------------------------------------------------------
1 启动数据库: 根据路径启动电脑上的, MongoDB 服务器 (可在全局执行此命令)
mongod --dbpath "D:\mongodb\data"
2 启动后端代码
后端文件根目录: npm start
---------------------------------------------------------------------------
3 商品列表, 调接口
---------------------------------------------------------------------------
---------------------------------------------------------------------------