zoukankan      html  css  js  c++  java
  • Dva.js 入门级教学文档-2

    Dva.js 入门级教学文档-2

      • 简介
      • 四、Model 包下文件架构(重点)
        • 1、namespace
        • 2、state
        • 3、reducers
          • (1)、save
          • (2)、state
          • (3)、action
          • (4)、payload
          • (5)、return
        • 4、effects
          • (1)、*
          • (2)、query
          • (3)、payload
          • (4)、call
          • (5)、put
          • (6)、select
        • (5)、subscription
      • 五、connect 连接 Model 和 Route 页面下的数据
      • 六、初始化数据 和 Model 数据比对
        • 1、初始化数据
        • 2、Model -> state
      • 七、数据显示和操作的流程
        • 1、编写 Route 页面
        • 2、编写 Model 层代码
        • 3、编写 初始化数据
        • 4、修改路由配置
        • 5、使用 connect 连接
        • 6、前台调用 Model 层方法
        • 7、数据在 Model 中的流向
      • 八、稍复杂概念
        • 1、多次调用
        • 2、多任务调度
          • 并行
          • 竞争
          • 子任务

    简介

    你好!

    本人为 2019.7 毕业的应届毕业生,目前从事前端工程师的职业。对知识充满渴望。如果本文中有什么错误的地方,还请各位指正。谢谢。

    本文的定位为给还没接触过 Dva,想在 Dva 入门的世界里够得到门把的小伙伴们。

    本文有参考 Dva.js 官网。想快速入手请看本教程。想正统的学习 Dva 知识,请看官网。

    本次教程共分为两个文档,这是第二部分(四、五、六、七)。

    如果还未看第一部分的小伙伴们,请先看 第一部分 的知识。

    先给小伙伴们看一下本文的目录架构:

    • 一、介绍
    • 二、环境搭建和使用
    • 三、全局架构
    • 四、Model 包下文件架构
    • 五、connect 连接 Model 和 Route 页面下的数据
    • 六、初始化数据 和 Model 数据比对
    • 七、数据显示和操作的流程
    • 八、稍复杂概念

    四、Model 包下文件架构(重点)

    1、namespace

    官网解释:当前 Model 的名称。整个应用的 State,由多个 Model 的 State 以 namespace 为 key 合成的。

    官网解释很绕,通俗的说:就是给每个 Model 一个命名用作 key 的标识。一般命名方式等于 Model js 的 文件名,举个例子:

    Model 文件 home.js 里 namespace 值可以设为:home

    2、state

    该 Model 当前的状态。每个 Model 的数据都保存在这里,这里的数据通过 Route 视图层的 this.props,直接显示在页面上。

    这里的数据一改变,页面上的数据也将自动改变。

    3、reducers

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

    上面说的同步是同步什么呢?同步该 Model 里面的 state 的数据。

    打开项目中 models example.js。找到 reducers,我将他复制在下方,来讲解一下怎么创建 reducers 下的方法。

    reducers: {
        save1(state, action) {
            return { ...state, ...action.payload };
        },
        save2(state, action) {
            return { ...state, ...action.payload };
        },
    },
    

    (1)、save

    save:为一个普通方法的命名,可自行取名

    (2)、state

    state:为当前 Model 下的所有 state 值,可以 console.log(state) 看一下输出就知道了。

    (3)、action

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

    (4)、payload

    payload:就是 action 里传递过来的数据。可以 console.log(action.payload) 看一下输出就知道了。

    (5)、return

    return:返回的是新的 state。等于舍弃了旧的 state,重新 return 一个新的 state 作为当前 Model 的 state

    一般情况下,我们要解开旧的 state,将它重新赋值给新的 state...state 为 ES6 语法。

    将操作完成得数据累加到 return 中。

    同名的数据会覆盖,所以不用担心旧的 state 值会影响到新设置的值。

    不同名的数据会追加。

    4、effects

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

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

    来看看例子:

    import { querySomething } from '@/services/api';
    
    *query({ payload }, { call, put, select }) {
        const data = yield call(querySomething, payload);
        console.log(data)
        yield put({
        type: 'save1',
        payload: { name: data.text },
        });
    },
    

    (1)、*

    *:这个 * 符号,可能小伙伴们不熟悉,简单点,不管它,只要记住每个 effects 里方法前面都加上 * 即可。

    稍微解释一下:

    这表明它是一个异步函数,里面可以使用 yield 等待其他异步函数执行结果。

    (2)、query

    query:方法名,自定义命名。不多解释。

    (3)、payload

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

    payload 就是存放在 action 里面的数据。可以 console.log(payload) 看输出的效果。

    (4)、call

    call:与后台服务端接口进行交互。

    第一个传参:后台服务器接口对应的名称。第二个参数:入参。

    同行的 data 为出参。可以 console.log(data) 看输出的效果。

    (5)、put

    put:用来发出事件,即 action。一般调用 reducers 下的方法进行同步数据。

    type:该 Model 层里 reducers 下的方法名。

    payload:参数的传递。

    如此一来。我们就将服务端查出来的数据,传递给 reducers 进行同步数据的操作了。

    (6)、select

    select:如果我们需要调用到其他 Model 层里面的 state值。那么我们就需要用 select 来进行操作。

    const homeName = yield select(state => state.home);
    

    这样我们就可以取到名为 home 的 Model 层里面的 state 数据了。

    (5)、subscription

    Model 中的 subscription 相当于一个监听器,可以监听路由的变化、鼠标、键盘、服务器连接变化等。

    这样再其中可以根据不同的变化作出相应的处理。

    如果你只是入门级别的选手,其实不需要用到这个东西,我自己也没用过,放个例子你们看看。

    subscriptions: {
        setup:({ dispatch, history }) {
            window.onresize = () => {   //这里表示的当浏览器的页面的大小变化时就会触发里面的dispatch方法,这里的save就是reducers中的方法名
            dispatch (type:"save")  
          }
        },
        onClick ({dispatch}) {
          document.addEventListener('click',() => {   //这里表示当鼠标点击时就会触发里面的dispatch命令,这里的save就是reducers中的方法名
            dispatch (type:"save")
        })
    }
    

    五、connect 连接 Model 和 Route 页面下的数据

    dva 有提供 connect 方法。只要在每个 Routes 页面导入下面的代码即可。

    import { connect } from 'dva';
    

    如果细心的小伙伴已经发现了,Routes 下的页面定义的都是状态组件,而不是用 class ~ extends React.Components,这样的好处是:组件不被实例化,整体渲染性得到了提升。

    对于组件:

    我们在最后导出时使用 connect 进行与 Models 的连接。

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

    解释一下 index:

    index 为 Model 层里面的 namespace。只要补上上面的代码就可以了。是不是很快~

    六、初始化数据 和 Model 数据比对

    1、初始化数据

    这里指的是全局 index.js 里的 initialState,大家可以参考 第三大点->第1小点下:创建 dva 实例

    这里存放的是一个个以 model 下的 namespace 命名的对象;如果你随意命名的化页面是找不到你存放在这里的数据的。

    2、Model -> state

    这里也是用来存放数据对象的。

    两者的对比是:initialState 的优先级会高于 model => state,默认是 {},所以页面初始化时,读取到的数据是 initialState

    七、数据显示和操作的流程

    接下来我将用最简单的步骤从无到有的演示一遍 dva 的写法和数据传输的流向。

    不要看有那么多的步骤,其实每一步都很简短,很简单。

    1、编写 Route 页面

    class 的写法就是 class ~ extends React.Component{}

    这里我将用组件的形式演示一遍。

    import React from 'react';
    
    const Example = ({dispatch,全局 `index.js` 里你需要的参数对象名称}) => {
        return (<div></div>)
    }
    
    export default Example;
    

    这就是一个最简单的页面。

    2、编写 Model 层代码

    
    export default {
    
      namespace: 'example',
    
      state: {},
    
      effects: {
        *fetch({ payload }, { call, put }) {  // eslint-disable-line
          yield put({ type: 'save',payload:data });
        },
      },
    
      reducers: {
        save(state, action) {
          return { ...state, ...action.payload };
        },
      },
    };
    

    也是最简单的 Model 的格式,有任何不懂得地方请直接参考第四大点。

    3、编写 初始化数据

    在全局 index.js 里 修改下面这段代码:

    const app = dva({
        initialState: {
            example: {
                name:'nameText'
            }
        }
    })
    
    app.model(require('./models/example').default);     //还要记得补上这句话。在 index.js 里载入它。
    

    4、修改路由配置

    import Count from './routes/Example';
    
    <Route path="/example" exact component={Example} />
    

    5、使用 connect 连接

    在 Route -> example.js 页面上使用 connect

    修改代码:

    import { connect } from 'dva';
    
    export default connect(({ example }) => ({ example }))(Example);
    

    如此一来,在页面上通过 this.props 即可获取到 example 里得数据。

    6、前台调用 Model 层方法

    如果需要于后台交互,那么就需要将入参传递到后台的 Model 层进行服务器的交互。

    这里距需要讲解一下 dispatch了。

    dispatch:是一个用于触发 action(这里可以直接理解为:调用后台的 model 里的方法) 的函数。只是触发 Model 里的函数而已,并没有对数据进行操作。

    可以类比为一个引路人。

    来看一下前台怎么使用 dispatch 的。

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

    至此,我们就已经在页面上触发了 model 层里面的某个方法,并且把参数一起传递过去了。

    type:如果你不需要调用异步的话可以直接 example/save 调用 reducer 下的方法。

    7、数据在 Model 中的流向

    下面这些文字若有任何不懂的地方请直接参考上面的内容。

    如果你上一步是调用 异步(Effects) 里的方法的话

    那么你可以 console.log(dayload) 下,看看数据是否有传递过来。

    如果需要调用 服务端接口就使用 const data = yield call(接口名,参数名);,然后 console.log(data) 看看数据有没有查询出来。

    接着调用 yield put({ type:'save',payload:data }) 调用 将参数传递到 reducer 下的方法进行同步。

    来到 reducers 的方法下,进行数据操作,操作完成后用 return 将数据返回给 state

    八、稍复杂概念

    1、多次调用

    在一个 effect 中,可以使用多个 put 来分别调用 reducer 更新状态(state)。

    在一个 effect 中,可以存在多个 call 操作。

    2、多任务调度

    • 并行。若干任务之间不存在依赖关系,并且后续操作对他们的结果无依赖。
    • 竞争。只有一个完成,就进入下一个环节。
    • 子任务。若干任务,并行执行,全部做完之后,才能进入下一个环节。

    并行

    const [ result1,result2 ] = yield [
        call(service1,param1),
        call(service2,param2),
    ]
    

    竞争

    const { result1,result2 } = yield race({
        result1:call(service1,param1),
        result2:call(service2,param2),
    })
    

    子任务

    可以直接参照 上一点 多次调用 的方法。

  • 相关阅读:
    apply()与call()的区别
    VS Code 配置vue开发环境
    settimeout 和 setinterval
    JAVA内存泄漏和内存溢出的区别和联系
    Oracle Distinct(过滤重复)用法
    Oracle Order By排序用法详解
    Oracle Select语句
    登陆权限--token的使用
    登陆权限--token 的生成和验证
    MySQL基础增删改查
  • 原文地址:https://www.cnblogs.com/wangking/p/13671638.html
Copyright © 2011-2022 走看看