几天时间按照尚硅谷提供的资源做了一个后台管理的项目,放到gitee上了:
https://gitee.com/aniu251700/react-admin
熟练了部分常用的react语法,还有用到了redux状态管理,大致效果如下:
1). 描述项目
2). 技术选型
3). API接口/接口文档/测试接口
1). 使用react脚手架创建项目
2). 开发环境运行: npm start
3). 生产环境打包运行: npm run build serve build
1). 创建远程仓库
2). 创建本地仓库
a. 配置.gitignore
b. git init
c. git add .
d. git commit -m "init"
3). 将本地仓库推送到远程仓库
git remote add origin url
git push origin master
4). 在本地创建dev分支, 并推送到远程
git checkout -b dev
git push origin dev
5). 如果本地有修改
git add .
git commit -m "xxx"
git push origin dev
6). 新的同事: 克隆仓库
git clone url
git checkout -b dev origin/dev
git pull origin dev
7). 如果远程修改
git pull origin dev
api: ajax请求的模块
components: 非路由组件
pages: 路由组件
App.js: 应用的根组件
index.js: 入口js
下载antd的包
按需打包: 只打包import引入组件的js/css
下载工具包
config-overrides.js
package.json
自定义主题
下载工具包
config-overrides.js
使用antd的组件
根据antd的文档编写
下载包: react-router-dom
拆分应用路由:
Login: 登陆
Admin: 后台管理界面
注册路由:
1). 自定义了一部分样式布局
2). 使用antd的组件实现登陆表单界面
Form / Form.Item
Input
Icon
Button
1). form对象
如何让包含
1. 高阶函数 1). 一类特别的函数 a. 接受函数类型的参数 b. 返回值是函数 2). 常见 a. 定时器: setTimeout()/setInterval() b. Promise: Promise(() => {}) then(value => {}, reason => {}) c. 数组遍历相关的方法: forEach()/filter()/map()/reduce()/find()/findIndex() d. 函数对象的bind() e. Form.create()() / getFieldDecorator()() 3). 高阶函数更新动态, 更加具有扩展性2. 高阶组件 1). 本质就是一个函数 2). 接收一个组件(被包装组件), 返回一个新的组件(包装组件), 包装组件会向被包装组件传入特定属性 3). 作用: 扩展组件的功能 3. 高阶组件与高阶函数的关系 高阶组件是特别的高阶函数 接收一个组件函数, 返回是一个新的组件函数
启动后台应用: mongodb服务必须启动使用postman测试接口(根据接口文档): 访问测试: post请求的参数在body中设置 保存测试接口 导出/导入所有测试接口
1). ajax请求函数模块: api/ajax.js 封装axios + Promise 函数的返回值是promise对象 ===> 后面用上async/await 自己创建Promise 1. 内部统一处理请求异常: 外部的调用都不用使用try..catch来处理请求异常 2. 异步返回是响应数据(而不是响应对象): 外部的调用异步得到的就直接是数据了(response --> response.data)2). 接口请求函数模块: api/index.js 根据接口文档编写(一定要具备这个能力) 接口请求函数: 使用ajax(), 返回值promise对象3). 解决ajax跨域请求问题(开发时) 办法: 配置代理 ==> 只能解决开发环境 编码: package.json: proxy: "http://localhost:5000"4). 对代理的理解 1). 是什么? 具有特定功能的程序 2). 运行在哪? 前台应用端 只能在开发时使用 3). 作用? 解决开发时的ajax请求跨域问题 a. 监视并拦截请求(3000) b. 转发请求(4000) 4). 配置代理 告诉代理服务器一些信息: 比如转发的目标地址 开发环境: 前端工程师 生产环境: 后端工程师5). async和await a. 作用? 简化promise对象的使用: 不用再使用then()来指定成功/失败的回调函数 以同步编码(没有回调函数了)方式实现异步流程 b. 哪里写await? 在返回promise的表达式左侧写await: 不想要promise, 想要promise异步执行的成功的value数据 c. 哪里写async? await所在函数(最近的)定义的左侧写async
login.jsx 1). 调用登陆的接口请求 2). 如果失败, 显示错误提示信息 3). 如果成功了: 保存user到local/内存中 跳转到admin 4). 如果内存中的user有值, 自动跳转到adminsrc/index.js 读取local中user到内存中保存admin.jsx 判断如果内存中没有user(_id没有值), 自动跳转到loginstorageUtils.js 包含使用localStorage来保存user相关操作的工具模块 使用第三库store 简化编码 兼容不同的浏览器memoryUtils.js 用来在内存中保存数据(user)的工具类
1). 整体布局使用antd的Layout组件2). 拆分组件 LeftNav: 左侧导航 Header: 右侧头部3). 子路由 定义路由组件 注册路由
1). 使用antd的组件 Menu / Item / SubMenu2). 使用react-router withRouter(): 包装非路由组件, 给其传入history/location/match属性 history: push()/replace()/goBack() location: pathname属性 match: params属性3). componentWillMount与componentDidMount的比较 componentWillMount: 在第一次render()前调用一次, 为第一次render()准备数据(同步) componentDidMount: 在第一次render()之后调用一次, 启动异步任务, 后面异步更新状态重新render4). 根据动态生成Item和SubMenu的数组 map() + 递归: 多级菜单列表 reduce() + 递归: 多级菜单列表5). 2个问题? 刷新时如何选中对应的菜单项? selectedKey是当前请求的path 刷新子菜单路径时, 自动打开子菜单列表? openKey是 一级列表项的某个子菜单项是当前对应的菜单项
1). 界面静态布局 三角形效果2). 获取登陆用户的名称显示 MemoryUtils3). 当前时间 循环定时器, 每隔1s更新当前时间状态 格式化指定时间: dateUtils4). 天气预报 使用jsonp库发jsonp请求百度天气预报接口 对jsonp请求的理解5). 当前导航项的标题 得到当前请求的路由path: withRouter()包装非路由组件 根据path在menuList中遍历查找对应的item的title6). 退出登陆 Modal组件显示提示 清除保存的user 跳转到login7). 抽取通用的类链接按钮组件 通过...透传所有接收的属性: xxxx 组件标签的所有子节点都会成为组件的children属性
1). jsonp只能解决GET类型的ajax请求跨域问题2). jsonp请求不是ajax请求, 而是一般的get请求3). 基本原理 浏览器端: 动态生成