当前位置: 首页 > news >正文

基于react的前端项目开发和实战总结(umi框架)

本文介绍了基于react的前端项目开发方法及常用基础知识,实战案例主要是基于umi框架。

主要内容包括:

1)Umi项目目录结构约定;

2)核心概念如Umi框架、Dva状态管理及其与React的配合使用;

3)React与Vue在数据流、组件通信等方面的差异;

4)开发技能要点,包括Dva模型定义、组件编写、父子组件通信方法;

5)状态管理机制对比(put、localStorage、useState)。

重点阐述了在Umi项目中如何通过Dva管理状态、实现组件间通信,以及React单向数据流下父子组件传值的特点。

一、目录结构

umi结构

|- src/

|-   |-pages/     # 页面目录(约定式路由)

|-   |-models/    # dva 状态模型【掌握通信方法和写法】

|-   |-components/ #自定义组件【子组件和父组件-嵌套使用及通信方式;组件编写方法】

|-   |-layouts/  # 全局布局组件

|-   |-assets/ # 字体和图片

|-   |-config/ # 接口定义和静态数据

|-   |-app.tsxe # 应用入口配置

|-   |-.umi #自动生成的运行时文件

|-   |-.config/

|-   |-    |-routes.ts #路由配置(可选)

|-   |-    |-umirc.ts  # umi配置文件【环境配置时用到】

|-   |- package.json【项目元数据和配置信息:scripts 脚本; gitHooks 钩子;dependencies 依赖】|-   |--tsconfig,json # 编译选项

- README.md

二、基本概念

1、umi框架

        umi是一个由蚂蚁金服推出的 React 应用框架,旨在简化React应用的开发流程,提供开箱即用的工程化能力和插件化扩展机制。

2、dva 框架

        dva是一个状态管理框架,它整合了React、Redux和Redux-saga,帮助开发者更轻松地管理应用的状态和处理异步逻辑。

        (1)redux 状态管理

          通过model组织状态、更新逻辑和副作用状态的容器,包含 state(状态)、reducers(同步更新)和 effect(异步操作)等;

        (2)Redux Saga,支持通过 effects 处理异步操作;

3、umidva 的关系

  (1)umi是框架,dva 是状态管理库;

    umi提供路由、构建、插件等整体框架能力,而 dva 专注于状态管理(类似 Redux+saga 的封装);

(2)umi集成 dva:通过插件 @umijs/plugin-dva,umi可以无缝集成 dva 的 model 机制简化状态管理。示例:在 umi项目中启用 dva 插件后,开发者只需在 src/models 目录下编写 dva 的 model 文件,umi会自动将其注入到应用中。

4、react 和 vue 的区别

(1)vue 的双向绑定:通过 v-mode:直接同步表单输入与状态,减少样板代码,适合表单密集场景(如后台管理系统)

(2)react 的单向数据流强调数据流的可预测性,适合复杂状态逻辑(如大型应用、需要严格调试的项目)。

因此父子组件中,需要子组件改变数据的场景中,父组件可以传给子组件方法,在model中方法与数据绑定,子组件调用方法便改变了数据;而不能直接传数据给子组件。

而vue在父子组件中,只能传递数据,不能传递方法。子组件改变数据,因为双向绑定,数据流向是双向的,父组件数据随之自动改变

(3)vue要手动配置路由,react通过页面目录自动映射

5、页面开发主要技术概念

单页面开发主要掌握dva通信和父子组件通信方法,其他的组件引入使用可参考开发手册;

(1)model:状态和业务逻辑的容器,包含state(状态)、reducers(同步更新)和effects(异步操作)。

(2)componentReact 组件,通过 connect 方法与 Model 绑定,访问状态或触发更新

三、主要开发技能(重要)

如下是示例页面的开发

|- src/

|-   |-pages/ 

|-   |-    |-desk/nstitution-switch

|-   |-    |-   |-index.js

|-   |-    |-    |-models/

|-   |-    |-    |- |-institution_switch_model.js

1、路由定义

在 umi 下,根据文件目录自动生成路由

如图所示:

路由地址:/desk/institution-switch

2、dva

(1)institution_switch_model.js是model

(src/pages/desk/institution-switch/models/institution_switch_model.js

(2)index.js 是组件

(3)两者通过 dva().connect 实现绑定

3、model

model 定义方法和用到的数据,并通过 dva 进行状态管理。文件结构有点类似 vue 的全局文件存储 state 管理。

主要分为:state、reducers、effects、subscriptions

  1. namespace:和文件夹同名(model 命名)
  2. state:变量
  3. reducers: 用于更新 state 的内容,通常被 effects 的方法调用

如:

reducers: {update (state, { payload: obj} ) {return {...state,...obj }}
}

effect使用方法:

yield put({ type: 'update’, payload: { switchConfiglist: resultData|| []} })

4、effects :

操作的方法,提供给组件调用,改变state的数据

*querySwitchConfigList ({ payload: obj}, { put} ) {const resultData = yield.post(QUERY INSTITUTION SWITCH CONFIG LIST, obj)}

注意:
(4.1) 前面要加*

(4.2)命名方法:

{payload: obj} ,用于提取 payload 属性幷重命名为 obj

{payload},用于提取 payload 属性,并且保持其名称不变

(4.3)effects 里的方法相互调用

yield put({

type:方法名,

payload:{***},

})

区别于 vue 的直接 this.方法名

5、subscriptions

监听路由变化和定时器

subscriptions 在 dva(基于 Redux 和 Redux-Saga 的数据流方案)中用于订阅一些数据源,比如路由变化、Websocket 消息、定时器等,并根据需要 dispatch action。在代码中,subscriptions 主要用于监听路由变化action 以更新 state,并在进入特定路径时 dispatch一个action 以更新 state。

示例:

subscriptions: {setup ({ dispatch, history}) {history.listen(({pathname))=>{if (pathname.indexOf(‘/desk/nstitution-switch’)>1){dispatch({type: 'update', payload: { switchConfigList: []),})}}),}},

如上访问/desk/institution-switch 页面(列表页面),先清空教据

6、组件

[代码主要组成部分: ]

function RuleInfo({dispatch, 对应model定义的变量switchConfigList,modelData1..}){

//数据定义(初始化绑定 model)

const data1 =modelData1(对应model定义的变量)

...

// 数据定义(自定义)

const [data2, setData2]= useState(false)

// 方法定义(绑定model)

//  type为路由路径,由文件路径自动映射,加上 model名称。

const functionA = (param) => {

dispatch( {type:’rule info mode/queryCommonRuleBusinessOptions’,

payload: { param }})

}

// 方法定义(自定义)

.......

}

//刚进入页面时执行的方法,类似vue的create()

useEffect(()=>{

functionA()}, [])

})

// 组件页面布局

return (

<div>

<父组件>

        <子组件

        propa = {data1 }

        propb = (data2 }

        propc = {functionA }

        </子组件>

</父组件>

</div>

 )

}

//用 dva 的 connect 将组件和 model 绑定

const mapStateToProps = (state)=>{

// 变量引用 model 的 state,变量命名和文件开头的入参一样

const { switchConfigList }= state.institution_switch

// 方法引用

const tableLoading state.loading.effects['institution-switch/quenySwitchConfigList

//变量命名和本文件开头的入参一样

return {tableLoading,switchConfigList,}

}

export defaut connect(mapStateToProps)(SwitchConfigPage);

注意

(1) model 的 effect 调用方法是 yield put(type:方法名)

组件调用方法是 dspatch(type:路径)

(2) 父子组件里赋值传递的不能直接是 effect 的,还要在数掘定义和方法定义中重新定义,初始化成 effect 的值并绑定。

(3) 父子组件传递的可以是变量和方法,在 vue 里只能传递变量;

***为什么传递方法呢***

方法在 model 里,可以操作 state 数据,相当于方法和激据绑定在 react 数据是单向流动,只能从父组件流向子组件,所以子组件里的数倒改动影响不了父组件;

因此此时就要传递方法,因为方法和数据定,子组件调用方法后,方法再改变数据;

区别于 vue,vue 是动态双向绑定,子组件数据通过prop 绑定后,子组件对数据的改动,便是对全局父组件数据的改动。

7、父子组件的通信

上述讲了 dva 之间的通信,接下来是父子组件的

function Rulelnfo ({

propa,propb,propc(父组件里插入子组件时,对应左边的命名)

}){

// 自定义数据

const test1;

// 自定义方法

const testfun1,

return (

<div>

<二级子组件

twoComponentdata1={test1}

twoComponentData2={propa}

twoComponentFunction2={propb}

/>

</div>

注意:

和 dva 的数据传递不同,dva 和 model 之间传递数据(右边的),先要在组件里面定义自己的变量,然后绑定到值 model的变量,有中间的一步,不直接使用。

但是父子组件的通信,可以直接使用,方法和变量都可以直接便用组件传过来的,没有中间的一步;也可以使用自定义的方法变量。

四、其他问题

1、useState ,locaiState , useEffect

useState 组件实例内存;localstate 硬存;

useState 和 useEffect 的作用

useState 钩子用于在函数组件中添加状态。它允许你声明一个状态变量,并提供一个用于更新该状态的函数。这是 React函数组件中管理状态的主要方式。

useEffect 钩子用于在函数组件中执行副作用操作。副作用操作包括数据获职、订阅设置手动修改 DOM 等。

这两个钩子是 React 函数组件开发中非常基础和重要的工具。

在 React 函数组件中,如果直接给一个状态变量(如 switchChecked)赋值,而不是通过 useState 或其他 React 提供的状态管理方法来更新状态,React 将无法跟踪状态的变化并触发组件的重新渲染。这会导致 UI不会反映出状态的最新值。

2、存储机制 put、localStorage 和 useState

put、localstorage 和 useState 分别对应不同级别的存储机制,具体如下:

存储级别:

应用级别:put 用于在应用中全局管理状态,适用于需要在多个组件之间共享的状态。put 是 Redux 或 Redux-Saga 中用于 dispatch action 的函数,用于在应用中全局管理状态。

客户端级别:localstorage 存储在用户的浏览器中,适用于需要在多个页面或会话之间共享的数据。

组件级别:useState 用于在单个组件内部管理状态,适用于局部状态管理。

3、方法调用:

在典型的 Redux-Saga 架构中

(1).组件 dispatch-个 action(如'main/getuserInfo')

(2).saga 监听这个 action,执行 API 调用

(3).saga收到响应后:dispatch个新actio

(如'main/getuserInfosuccess')

(4).Reducer 处理这个新 action,将数据存储在 store 中

(5).组件通过 mapstateToProps 从 store 中获取数据

http://www.dtcms.com/a/395308.html

相关文章:

  • 【iOS】YYModel
  • 修改docker配置使其支持本机tcp连接
  • ReportFragment:Android 生命周期的桥梁与兼容性解决方案
  • 力扣Hot100--234.回文链表
  • 视觉语言大模型(VLM)的产业落地:从Qwen-VL技术解析到医疗、车险行业革新
  • 零基础新手小白快速了解掌握服务集群与自动化运维(七)Nginx模块--Nginx Web服务
  • 一个硬盘选MBR 还是GPT
  • 【含文档+PPT+源码】基于GPT+SpringBoot的个人健康管理与咨询系统设计与实现
  • 【项目实战 Day5】springboot + vue 苍穹外卖系统(Redis + 店铺经营状态模块 完结)
  • 旧衣回收小程序:非技术视角下的价值重构与发展前景
  • 使用vue-i18n实现语言切换
  • 做小程序找哪家公司,解析小程序开发定制公司哪家适合你
  • 【python】python进阶——math模块
  • NHD-6108 全自动远、近光检测仪:智能高效的汽车灯光检测方案
  • 《 Linux 点滴漫谈: 一 》开源之路:Linux 的历史、演进与未来趋势
  • C#和微软System.Speech.Synthesis库实现语音合成
  • C++概述 (一)
  • 【开题答辩全过程】以 基于springboot的高校仪器共享管理系统设计和实现为例,包含答辩的问题和答案
  • 【python】FastAPI简介
  • IDEA lombok注解无效的问题,运行时提示java: 找不到符号或者方法
  • Windows 系统部署 Kronos 金融 K 线基础模型——基于 EPGF 架构
  • 010 Rust流程控制
  • MyBatisPlus快速入门:简化CRUD操作
  • 网络编程套接字(三)---简单的TCP网络程序
  • 背景建模(基于视频,超炫)项目实战!
  • ios26版本回退到ios18
  • OpenCV直方图比较:原理与四种方法详解
  • OpenCV - 图像金字塔
  • 寄存柜频繁维护还卡顿?杰和IB2-281主板:智能化升级高效省心
  • 海外短剧系统开发:多语言适配与跨地区部署的架构实践