umi3 使用 dva 的流程及理解(model数据使用教程)

本文详细介绍了DVA框架中Model的结构,包括Reducer处理同步操作、Effects管理异步逻辑、subscriptions订阅数据源,并展示了如何通过call、select和put进行数据交互。重点讲解了如何连接Model与组件,以及如何通过param和query传递参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在dva中主要分3层,models,services,components,其中models是最重要概念,这里放的是各种数据,与数据交互的应该都是在这里。services是请求后台接口的方法。components是组件了。

本文主要讲model的使用.
下面是model的基本结构

{   namespace: String, // 命名空间名字,必填     
//namespace: 'global' 说明以下此处的dva命名空间为 global,即你调用的时候需要采用 global.XXX 的形式   
state: Object, // 状态   
reducer: Object, // 同步更新 state 修改状态  
 effects: Object, // 副作用:处理异步逻辑     
 //当数据需要从服务器获取时,需要发起异步请求,请求到数据之后,通过调用 Reducers更新数据到全局state   
 subscriptions: Object // 订阅数据源
 }

1.reducer

用来处理同步操作。如果不需要调接口时候,我们前台传递的 action(不懂的小伙伴不着急,下面有微讲解) 可以直接调用 reducers
里的方法。

reducer是一个函数,接收state 和 action,返回老的或新的state。 即: save(state, action) {
return { …state, …action.payload }; },

state:为当前 Model 下的所有 state 值,可以 console.log(state) 看一下输出就知道了。
action:当前台页面需要进行数据操作时,就会创建一个 action,action 存放了传递过来需要对当前 state 进行改变的数据。

reducers:{
changeTitle(state, { payload: { num }){ 
//changeTitle可以理解为一个方法名 
//payload:就是 action 里传递过来的数据。
//num 是传过来的,名字随便起,不是state中的num,这接收一个action

return {...state,...num}

//return:返回的是新的 state。等于舍弃了旧的 state,重新 return 一个新的 state 作为当前 Model 的 state。
//一般情况下,我们要解开旧的 state,将它重新赋值给新的 state。...state 为 ES6 语法。
//将操作完成得数据累加到 return 中。
//同名的数据会覆盖,所以不用担心旧的 state 值会影响到新设置的值。
//不同名的数据会追加。

},
//页面调用

//页面使用dispatch进行使用
this.props.dispatch({
      type: 'pageModel/changeTitle',  //namespace+需要调用的reducer方法
      payload: 'Hello World',
    });
  };

2.effects

用来处理异步操作。如果需要调取接口的话,前台页面就需要调用 effects 里的方法。

将数据取出来,在传递给 reducers 里的方法进行数据操作和同步 state。

Dva 中的异步操作都放到 effects 中管理,基于 Redux-saga 实现 Effect 是一个 Generator函数,内部使用 yield 关键字,标识每一步的操作

每一个 effect 都可以接收两个参数:

  1. 包含 dispatch 携带参数 payload 的 action 对象
  2. dva 提供的 effect 函数内部的处理函数集

第二个参数提供的处理函数中,常用的有 call、put、select call: 执行异步函数 put: 发出一个 Action,类似于
dispatch 触发reducer改变state select: 返回 model 中的 state //用于从state里获取数据

1.call

 *deleteOne({ payload }, { call }) {
 //deleteOne方法名,payload是传来的参数,是个对象,如果没参数可以写成{_,{call, put}}
//*:这个 * 符号,可能小伙伴们不熟悉,简单点,只要记住每个 effects 里方法前面都加上 * 即可。
//(这表明它是一个异步函数,里面可以使用 yield 等待其他异步函数执行结果。)

//payload:当前台页面需要进行数据操作时,就会创建一个 action,
//action 存放了传递过来需要对当前 state 进行改变的数据。
//payload 就是存放在 action 里面的数据。


const rsp = yield call(cardsService.deleteOne,{num:payload.numCount});
//call:与后台服务端接口进行交互。
//第一个传参:后台服务器接口对应的名称。第二个参数:入参。
//cardsService是引入service层那个js的一个名字,num是后台要求传的参数,rsp就是后台返回来的数据
// 请求成功之后,调用 reducer 更新 state
service中异步请求(cardsService.js)
request 是我们封装的一个网络请求库   
 async function deleteOne(data) {
   return request("queryFromApi", {
      data,
    method: "post",
    dataType: "payload"
  })   }

2.select

 *deleteOne({ payload }, { select, put }) {
  effects:{
    const m = yield select((state) => state.test.num)
    //select就是用来选择上面state里的数据
    }

3.put

yield put({
   type: "addNum",
 // put:用来发出事件,即 action。一般调用 reducers 下的方法进行同步数据。
//type:该 Model 层里 reducers 下的方法名。
//payload:参数的传递。
      payload: {
     num: data, 
   // 把后台返回的数据赋值给了num
  //假如那个reducer中方法是由这里effects去触发的,那个num名必须是这里名字num,如果reducer中方法不是这触发,那名字可随便起
      return rsp;
    },
}
}

3.subscriptions

// 订阅监听,比如我们监听路由,进入页面就如何,可以在这写
  setup ({ dispatch, history, query }) {
   return history.listen(
   async ({ pathname, search, query}) => {
      if (pathname==="/testdemo") 
      {// 当进入testdemo这路由,就会触发fetchUser方法
              dispatch({ type: "fetchUser" })
              }
          })
      }

4.connect

connect 连接 Model 和 Route 页面下的数据
dva 有提供 connect 方法。只要在每个 Routes 页面导入下面的代码即可。

import { connect } from 'dva';

对于组件:
我们在最后导出时使用 connect 进行与 Models 的连接。

export default connect(({index}) => ({index}))(IndexPage);

//解释一下 index:

index 为 Model 层里面的 namespace。

前台调用 Model 层方法

const { dispatch } = this.props; 
//在 dva 中,可以通过 `this.props` 直接取得 `dispatch`
dispatch ({
    type:'example/fetch',  //指定哪个 model 层里面的哪个 方法
    payload:{name:'exampleNew'}, 
     //需要传递到 model 层里面的参数。
     //payload 为固定用法(我自己的理解)。
})

5.parame和query传值

query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示

使用 `umi` 或 `dva` 这类基于 React 的框架时,`useModel()` 是一个 Hook,用于在函数组件中订阅并使用 `dva` 模型。`dva` 是一个轻量级的前端框架,它基于 React,提供了一套简单易用的状态管理方式。使用 `useModel()` 可以非常方便地连接到 `dva` 定义的 model,实现状态的订阅和更新。 在函数组件中使用 `useModel()` 的基本步骤如下: 1. 首先,确保你已经在项目中引入了 `dva` 相关的包,并且使用了 `dva` 配置应用。 2. 然后,在你的函数组件文件中引入 `useModel`。 3. 在函数组件内部调用 `useModel()`,传入你想要使用model 的 `namespace` 和对应的 `state`、`dispatch` 的名称。 4. `useModel()` 会返回一个包含 `state` 和 `dispatch` 的数组,你可以通过解构的方式来使用它们。 下面是一个使用 `useModel()` 的示例代码: ```javascript import React from &#39;react&#39;; import { useModel } from &#39;dva&#39;; function MyComponent(props) { // 假设 &#39;counter&#39; 是定义在 dva model 中的 namespace const [counterState, { increment }] = useModel(&#39;counter&#39;); return ( <div> <p>{counterState.count}</p> <button onClick={increment}>+</button> </div> ); } ``` 在这个例子中,`useModel(&#39;counter&#39;)` 用于订阅 `counter` 这个 model 的状态,`counterState` 将会包含 `counter` model 中定义的状态。`increment` 是一个从 `counter` model 中导出的 `dispatch` 函数,用于更新状态。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值