资讯专栏INFORMATION COLUMN

尚学堂 react -后台管理系统开发流程

lemon / 1906人阅读

摘要:项目开发准备描述项目技术选型接口接口文档测试接口启动项目开发使用脚手架创建项目开发环境运行生产环境打包运行管理项目创建远程仓库创建本地仓库配置将本地仓库推送到远程仓库在本地创建分支并推送到远程如果本地有修改新的同事克隆仓库如果远程修

day01 1. 项目开发准备
1). 描述项目
2). 技术选型 
3). API接口/接口文档/测试接口
2. 启动项目开发
1). 使用react脚手架创建项目
2). 开发环境运行: npm start
3). 生产环境打包运行: npm run build   serve build
3. git管理项目
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
    
4. 创建项目的基本结构
api: ajax请求的模块
components: 非路由组件
pages: 路由组件
App.js: 应用的根组件
index.js: 入口js
5 引入antd
下载antd的包
按需打包: 只打包import引入组件的js/css
    下载工具包
    config-overrides.js
    package.json
自定义主题
    下载工具包
    config-overrides.js
使用antd的组件
    根据antd的文档编写
    
6. 引入路由
下载包: react-router-dom
拆分应用路由:
  Login: 登陆
  Admin: 后台管理界面
注册路由:
  
  
  
  
7. Login的静态组件
1). 自定义了一部分样式布局
2). 使用antd的组件实现登陆表单界面
  Form  / Form.Item
  Input
  Icon
  Button
8. 收集表单数据和表单的前台验证
1). form对象
    如何让包含
的组件得到form对象? WrapLoginForm = Form.create()(LoginForm) WrapLoginForm是LoginForm的父组件, 它给LoginForm传入form属性 用到了高阶函数和高阶组件的技术 2). 操作表单数据 form.getFieldDecorator("标识名称", {initialValue: 初始值, rules: []})()包装表单项组件标签 form.getFieldsValue(): 得到包含所有输入数据的对象 form.getFieldValue(id): 根据标识得到对应字段输入的数据 3). 前台表单验证 a. 声明式实时表单验证: form.getFieldDecorator("标识名称", {rules: [{min: 4, message: "错误提示信息"}]})() b. 自定义表单验证 form.getFieldDecorator("标识名称", {rules: [{validator: this.validatePwd}]})() validatePwd = (rule, value, callback) => { if(有问题) callback("错误提示信息") else callack() } c. 点击提示时统一验证 form.validateFields((error, values) => { if(!error) {通过了验证, 发送ajax请求} })
9. 高阶函数与高阶组件
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. 高阶组件与高阶函数的关系
    高阶组件是特别的高阶函数
    接收一个组件函数, 返回是一个新的组件函数
    
day02 1. 后台应用
启动后台应用: mongodb服务必须启动
使用postman测试接口(根据接口文档):
    访问测试: post请求的参数在body中设置
    保存测试接口
    导出/导入所有测试接口
    
2. 编写ajax代码
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
        
3. 实现登陆(包含自动登陆)
login.jsx
    1). 调用登陆的接口请求
    2). 如果失败, 显示错误提示信息
    3). 如果成功了:
        保存user到local/内存中
        跳转到admin
    4). 如果内存中的user有值, 自动跳转到admin
src/index.js
    读取local中user到内存中保存
admin.jsx
    判断如果内存中没有user(_id没有值), 自动跳转到login
storageUtils.js
    包含使用localStorage来保存user相关操作的工具模块
    使用第三库store
        简化编码
        兼容不同的浏览器
memoryUtils.js
    用来在内存中保存数据(user)的工具类
    
4. 搭建admin的整体界面结构
1). 整体布局使用antd的Layout组件
2). 拆分组件
    LeftNav: 左侧导航
    Header: 右侧头部
3). 子路由
    定义路由组件
    注册路由
    
5. LeftNav组件
1). 使用antd的组件
    Menu / Item / SubMenu

2). 使用react-router
    withRouter(): 包装非路由组件, 给其传入history/location/match属性
    history: push()/replace()/goBack()
    location: pathname属性
    match: params属性

3). componentWillMount与componentDidMount的比较
    componentWillMount: 在第一次render()前调用一次, 为第一次render()准备数据(同步)
    componentDidMount: 在第一次render()之后调用一次, 启动异步任务, 后面异步更新状态重新render

4). 根据动态生成Item和SubMenu的数组
    map() + 递归: 多级菜单列表
    reduce() + 递归: 多级菜单列表

5). 2个问题?
    刷新时如何选中对应的菜单项?
        selectedKey是当前请求的path
    刷新子菜单路径时, 自动打开子菜单列表?
        openKey是 一级列表项的某个子菜单项是当前对应的菜单项
        
day03 1. Header组件
1). 界面静态布局
    三角形效果
2). 获取登陆用户的名称显示
    MemoryUtils
3). 当前时间
    循环定时器, 每隔1s更新当前时间状态
    格式化指定时间: dateUtils
4). 天气预报
    使用jsonp库发jsonp请求百度天气预报接口
    对jsonp请求的理解
5). 当前导航项的标题
    得到当前请求的路由path: withRouter()包装非路由组件
    根据path在menuList中遍历查找对应的item的title
6). 退出登陆
    Modal组件显示提示
    清除保存的user
    跳转到login
7). 抽取通用的类链接按钮组件
    通过...透传所有接收的属性: 
2. jsonp解决ajax跨域的原理
1). jsonp只能解决GET类型的ajax请求跨域问题
2). jsonp请求不是ajax请求, 而是一般的get请求
3). 基本原理
    浏览器端:
        动态生成

5. 使用redux及相关库编码
需要引入的库: 
    redux
    react-redux
    redux-thunk
    redux-devtools-extension(这个只在开发时需要)
redux文件夹: 
    action-types.js
    actions.js
    reducers.js
    store.js
组件分2类: 
    ui组件(components): 不使用redux相关API
    容器组件(containers): 通过connect()()生成的组件
    
day10 1. 在项目中搭建redux整套环境
1). store.js
2). reducer.js
3). actions.js
4). action-types.js
5). index.js
6). 在需要与redux进行状态数据通信(读/写)的UI组件包装生成容器组件
2. 通过redux管理头部标题headTitle数据
1). action-types.js
2). actoins.js
3). reducer.js
4). 相关组件: 
    left-nav.js
    header.js
    
3. 通过redux管理登陆用户信息user数据
1). action-types.js
2). actoin.js
3). reducer.js
4). 相关组件: 
    login.js
    admin.js
    left-nav.js
    header.js
    role.js
4. 自定义redux库
1). redux库向外暴露下面几个函数
    createStore(): 接收的参数为reducer函数, 返回为store对象
    combineReducers(): 接收包含n个reducer方法的对象, 返回一个新的reducer函数
    applyMiddleware() // 暂不实现

2). store对象的内部结构
    getState(): 返回值为内部保存的state数据
    dispatch(): 参数为action对象
    subscribe(): 参数为监听内部state更新的回调函数

3). combineReducers函数:
    返回的总reducer函数内部会根据总的state和指定的action, 
    调用每个reducer函数得到对应的新的state, 并封装成一个新的总state对象返回
5. 自定义react-redux库
1). react-redux向外暴露了2个API
    a. Provider组件类
    b. connect函数

2). Provider组件
    接收store属性
    通过context将store暴露给所有的容器子组件
    Provider原样渲染其所有标签子节点
    
3). connect函数
    接收2个参数: mapStateToProps和mapDispatchToProps
    connect()执行的返回值为一个高阶组件: 包装UI组件, 返回一个新的容器组件
    mapStateToProps: 
        为一个函数, 返回包含n个一般属性对象, 
        容器组件中调用得到对象后, 初始化为容器组件的初始状态, 并指定为UI组件标签的一般属性
    mapDispatchToProps:
        如果为函数, 调用得到包含n个dispatch方法的对象
        如果为对象, 遍历封装成包含n个dispatch方法的对象
        将包含n个dispatch方法的对象分别作为函数属性传入UI组件
    通过store绑定state变化的监听, 在回调函数中根据store中最新的state数据更新容器组件状态, 从而更新UI组件
day11 1. 数据可视化
1). echarts(百度) ==> echarts-for-react
2). g2(阿里) ==> bizCharts
3). d3(国外)
2. 前台404界面


3. 打包应用运行
1). 解决生产环境ajax跨域问题
    使用nginx的反向代理解决(一般由后台配置)
    CORS: 允许浏览器端跨域
2). BrowserRouter模式刷新404的问题
    a. 问题: 刷新某个路由路径时, 会出现404的错误
    b. 原因: 项目根路径后的path路径会被当作后台路由路径, 去请求对应的后台路由, 但没有
    c. 解决: 使用自定义中间件去读取返回index页面展现

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106635.html

相关文章

  • 1024程序员节最新福利之2018最全H5前端资料集

    摘要:前言有好久没有写博客了主要这段时间都沉迷学习无法自拔了哈哈自吹一波前两天不是节吗所以就有很多福利出现了当然每个人能都获得的信息都有所不同这就是所谓的信息差秉着好东西需要分享和开源的好习惯所以来给你们送福利了其他福利一程序员节最新福利之最全资 前言 有好久没有写博客了,主要这段时间都沉迷学习无法自拔了,哈哈.自吹一波. 前两天不是1024节吗,所以就有很多福利出现了,当然每个人能都获得的...

    xiongzenghui 评论0 收藏0
  • 1024程序员节最新福利之2018最全H5前端资料集

    摘要:前言有好久没有写博客了主要这段时间都沉迷学习无法自拔了哈哈自吹一波前两天不是节吗所以就有很多福利出现了当然每个人能都获得的信息都有所不同这就是所谓的信息差秉着好东西需要分享和开源的好习惯所以来给你们送福利了其他福利一程序员节最新福利之最全资 前言 有好久没有写博客了,主要这段时间都沉迷学习无法自拔了,哈哈.自吹一波. 前两天不是1024节吗,所以就有很多福利出现了,当然每个人能都获得的...

    googollee 评论0 收藏0
  • 初识React(7):高阶组件

    摘要:什么是高阶组件高阶组件,听着好像很高大尚,但是其实高阶组件就是一个函数的参数是组件,返回的是一个新的组件。在上面那个例子中,就是父级,继承了父级中的所有东西。 什么是高阶组件 高阶组件,听着好像很高大尚,但是其实高阶组件就是一个函数的参数是组件,返回的是一个新的组件。那么,高阶组件有什么好处呢,高阶组件可以减少代码冗余,把共有的代码提取出来,下面有个例子说明下: import Reac...

    printempw 评论0 收藏0
  • html5之canvas

    摘要:是新加的标签,主要有和,的应用是动画和图像,的应用是游戏渲染。 HTML5 Canvas canvas是html5新加的标签,主要有2D和3D,2D的应用是动画和图像,3D的应用是游戏渲染。 1. 2D基础 1.1绘制线 canvas window.onload = function(){ ...

    苏丹 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<