当前位置: 首页 > 工具软件 > dva > 使用案例 >

Dva笔记---kalrry

潘翰藻
2023-12-01

前言

Win配置记录
Mac配置记录

一、dva简介

dva简化了我们组件之间的数据通信(简化了我们之前在组件传值的时候使用的redux)

通过dva 就可以让我们更好的执行项目中数据传递的一个便捷性

dva=react-router(虽然dva中带有路由功能 可能工作中一般是吧dva和umi配合使用)+redux+redux-saga

简化完成一个redux的闭环 (dva和redux不是一个东西 他是redux的替代产品)

二、redux-saga

redux-saga是在redux中完成异步操纵的一个技术

三、创建

npm install -g dva-cli 全局下载

dva -v 查看版本

cd到指定文件夹下

dva new 项目名 创建项目

npm start 启动项目

四、dva路由

dva中也带路由功能 但是 在实际开发的时候 很多开发者喜欢把umi和dva整合在一起 umi管理路由 dva进行组件传值 各干各的事

1.创建路由组件页面

在src文件夹下的routes文件夹下创建即可

2.配置 在src下找到router.js进行配置

import React from 'react';
import { Router, Route, Switch } from 'dva/router';
import IndexPage from './routes/IndexPage';
// 1.引用
import Home from './routes/home';
import Phone from './routes/phone';

function RouterConfig({ history }) {
  return (
    <Router history={history}>
      <Switch>
        <Route path="/" exact component={IndexPage} />
        {/* 2.配置规则 */}
        <Route path="/home" exact component={Home} />
        <Route path="/phone" exact component={Phone} />
      </Switch>
    </Router>
  );
}

export default RouterConfig;

五、路由导航

声明式–Link

import {Link} from "dva/router"
export default ()=>{
    return (
        <>
            <Link to="/">默认页面</Link>&nbsp;&nbsp;&nbsp;
            <Link to="/home">home</Link>&nbsp;&nbsp;&nbsp;
            <Link to="/phone">phone</Link>&nbsp;&nbsp;&nbsp;
        </>
    )
}

编程式

编程式的方式和原生react的react-router-dom实现路由的方式是一样的

也要使用withRouter来设置不是被路由所管理的页面 具有路由的跳转对象

import {Link,withRouter} from "dva/router"
let Topbar= (props)=>{
    let fun=()=>{
        // 编程式导航
        props.history.push("/phone")
    }
    return (
        <>
            <Link to="/">默认页面</Link>&nbsp;&nbsp;&nbsp;
            <Link to="/home">home</Link>&nbsp;&nbsp;&nbsp;
            <Link to="/phone">phone</Link>&nbsp;&nbsp;&nbsp;
            <button onClick={fun}>点我进行页面的跳转phone</button>
        </>
    )
}
export default withRouter(Topbar)

六、dva-Model

model就是用来存放一个个的小模块 通过模块化的管理 可以弱化 组件数据与组件数据的耦合度

1.在src下的models文件夹下创建属于我们自己的数据模块

// 创建了一个phone组件的状态模块

export default {

    namespace: 'phonem',//命名空间  给当前这个模块起个名字必须写
  
    state: {//管理数据的

    },
  };
  

2.使用模块

把模块文件在index.js中进行配置引用

import dva from 'dva';
import './index.css';

// 1. Initialize
const app = dva();

// 2. Plugins
// app.use({});

// 3. Model
// app.model(require('./models/example').default);
app.model(require('./models/phonem.js').default);

// 4. Router
app.router(require('./router').default);

// 5. Start
app.start('#root');

3.组件内使用配置的模块

在组件内使用connect()高阶组件 来进行连接

import React, { Component } from 'react'
import Tb from "../components/topbar"
// 1.引用connect   connect是一个高阶组件
import {connect} from "dva"
 class phone extends Component {
    render() {
        return (
            <div>
                <Tb/>
               phone
               {/* 读取模块中的数据 */}
               {/* {this.props.state.命名空间.数据} */}
               {this.props.state.phonem.name}
            </div>
        )
    }
}
// connect是一个方法   只有这个方法被调用的时候才是一个高阶组件
export default connect(state=>({state}))(phone)

七、dva-state

state就是dva中的数据源 把所有的数据都存放在state中

// 创建了一个phone组件的状态模块

export default {

    namespace: 'phonem',//命名空间  给当前这个模块起个名字必须写
  
    state: {//管理数据的
        name:"xixi",
        age:18,
        arr:[1111,2222,3333,4444,5555]
    },
  };
  

八、dva–reducers

在dva的model中 我们使用reducers可以进行数据的修改操作

reducers中包含的就是一个个的函数 每一个函数就是一个修改的动作

export default {

    namespace: 'homem',
  
    state: {
        name:"xixi",
        age:18
    },
    // 数据修改
    reducers:{
        // 每一个函数就是一个数据的修改动作
        demoa(){

        },
        demob(){

        },
    }
  
  };
  

1.创建修改

export default {

    namespace: 'homem',
  
    state: {
        name:"xixi",
        age:18
    },
    // 数据修改
    reducers:{
        // 每一个函数就是一个数据的修改动作
        // state 数据源
        // payload 就是外部传递进来的数据
        demoa(state,payload){
            // 在函数中返回一个修改之后的结果
            return {...state,age:666}
        },
        demob(){

        },
    }
  
  };
  

2.组件中触发这个修改的动作

this.props.dispatch({type:“命名空间的名字/你要调用的reducers的名字”})

import React, { Component } from 'react'
import {connect} from "dva"

class home extends Component {
    fun=()=>{
        // 调用dva中的reducers进行数据的修改
        this.props.dispatch({type:"homem/demoa"})
    }
    render() {
        return (
            <div>
                我是dva---{this.props.state.homem.name}
                {this.props.state.homem.age}
                <button onClick={this.fun}>点我修改age</button>
            </div>
        )
    }
}
export default connect(state=>({state}))(home)

payload的使用

payload就是用来接受调用的时候传递进来的数据

1.传递数据的时候 在dispatch的方法中传递第二个参数

import React, { Component } from 'react'
import {connect} from "dva"

class home extends Component {
    fun=()=>{
        // 调用dva中的reducers进行数据的修改
        this.props.dispatch({type:"homem/demoa"})
    }
    funb=()=>{
        // 我给reducers的payload传递数据
        this.props.dispatch({type:"homem/demob",data:{text:"我是传递的数据"}})
    }
    render() {
        return (
            <div>
                我是dva---{this.props.state.homem.name}
                {this.props.state.homem.age}
                <button onClick={this.fun}>点我修改age</button>
                <button onClick={this.funb}>点我传递payload</button>
            </div>
        )
    }
}
export default connect(state=>({state}))(home)

2.在模块中可以使用payload来进行数据的接收

export default {

    namespace: 'homem',
  
    state: {
        name:"xixi",
        age:18
    },
    // 数据修改
    reducers:{
        // 每一个函数就是一个数据的修改动作
        // state 数据源
        // payload 就是外部传递进来的数据
        demoa(state,payload){
            // 在函数中返回一个修改之后的结果
            return {...state,age:666}
        },
        demob(state,payload){
            // console.log(payload.data)
            return {...state,age:payload.data.text}
        },
    }
  
   
  
  };
  

九、dva–基本的数据请求

1.在services下 设置我们的请求封装

import request from '../utils/request';

export function query() {
  return request('/api/users');
}
//我们自己的请求
export function apilink() {
  return request('http://localhost:3000/user/list');
}



2.在想使用请求的组件中 引用 使用

import React, { Component } from 'react'
import {connect} from "dva"

// 引用请求封装
import {apilink} from "../services/example.js"
class home extends Component {
    fun=()=>{
        // 调用dva中的reducers进行数据的修改
        this.props.dispatch({type:"homem/demoa"})
    }
    funb=()=>{
        // 我给reducers的payload传递数据
        this.props.dispatch({type:"homem/demob",data:{text:"我是传递的数据"}})
    }
    func=()=>{
        // 请求数据
        apilink().then((ok)=>{
            console.log(ok)
        })
    }
    render() {
        return (
            <div>
                我是dva---{this.props.state.homem.name}
                {this.props.state.homem.age}
                <button onClick={this.fun}>点我修改age</button>
                <button onClick={this.funb}>点我传递payload</button>
                <hr />
                <button onClick={this.func}>点我发送请求</button>
            </div>
        )
    }
}
export default connect(state=>({state}))(home)

当我们运行的时候发现请求会跨域

跨域

在dva中设置跨域 我们在webpackrc的文件中进行设置

写的内容同vue于react的跨域内容 使用proxy来进行跨域解决

{
     "proxy":{ //设置devServe解决跨域问题
            "/api":{
                // 我们需要告诉devserver帮我们解决那个地址的跨域
                "target":"http://localhost:3000/",
                "changeOrigin":true,
                "ws":true,
                // 替换地址
                "pathRewrite":{
                    "^/api":""
                }
            }
        }
}

千万不要忘了 把请求地址换成 /api 重启项目

十、dva — 异步操作方式effects

effect中是一个个的函数 每个函数就是一个异步操作

扩展—es6 Generator函数

Generator 有的人叫做迭代器函数 / 星号函数

通过generator函数 可以让我们在函数执行的时候 控制其内容的内容 走走停停 让函数交出执行权 可以让函数在调用的时候按照我们的需要执行或者暂停

传统的函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function fun(){
            console.log(1)
            console.log(2)
            console.log(3)
        }
        fun()
        // 在传统的函数中   只要函数被调用  那么函数中的所有代码
        // 都会从上到下 一次执行一遍
    </script>
</body>
</html>

我现在不想让函数一调用全部都执行 我想让他按照我的命令来执行怎么办?

generator基本概念

可以让我们在函数执行的时候 控制其内容的内容 走走停停 让函数交出执行权 可以让函数在调用的时候按照我们的需要执行或者暂停

要求

1.在生命函数点的时候 在 函数名前面加一个*号 用于区分和普通函数的区别

2.yield 分割线 通过分割线就可以指明我们需要函数在执行中的暂停位置

3.使用next()来执行函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function *fun(){
            console.log(1)
            yield
            console.log(2)
            yield
            console.log(3)
        }
        // console.log(fun())
        // 我们需要使用next()让他走走停停
        let g=fun()
        g.next()//执行
        g.next()//执行
        g.next()//执行
        
       
    </script>
</body>
</html>

dva异步请求数据

是吧数据请求在effect中进行数据请求 然后把请求来的数据交给 reducers进行修改 最终赋值给state

1.需要在页面有个事件触发 effects进行异步操作

this.props.dispatch({type:“命名空间的名字/你触发effects的名字”})

import React, { Component } from 'react'
import {connect} from "dva"
class phone extends Component {
    componentDidMount() {
        // 触发effects进行数据请求
        this.props.dispatch({type:"homem/demolink"})
    }
    
    render() {
        return (
            <div>
                <h1>dva数据请求闭环操作</h1>
            </div>
        )
    }
}
export default connect(state=>({state}))(phone)

2.就在模块中创建对应的effects

export default {

    namespace: 'homem',
  
    state: {
        name:"xixi",
        age:18
    },
    // 数据修改
    reducers:{
        // 每一个函数就是一个数据的修改动作
        // state 数据源
        // payload 就是外部传递进来的数据
        demoa(state,payload){
            // 在函数中返回一个修改之后的结果
            return {...state,age:666}
        },
        demob(state,payload){
            // console.log(payload.data)
            return {...state,age:payload.data.text}
        },
    },
    // 进行异步数据的操作
    effects:{
        // 对应的都是一个个的方法(Generator函数)  每个方法都是一个异步数据的操作
        *demolink({payload},{put,call}){

        }
    }
   
  
  };
  

3.在刚才创建的effect中进行异步操作

// 引用请求封装
import {apilink} from "../services/example.js"
export default {

    namespace: 'homem',
  
    state: {
        name:"xixi",
        age:18
    },
    // 数据修改
    reducers:{
        // 每一个函数就是一个数据的修改动作
        // state 数据源
        // payload 就是外部传递进来的数据
        demoa(state,payload){
            // 在函数中返回一个修改之后的结果
            return {...state,age:666}
        },
        demob(state,payload){
            // console.log(payload.data)
            return {...state,age:payload.data.text}
        },
    },
    // 进行异步数据的操作
    effects:{
        // 对应的都是一个个的方法(Generator函数)  每个方法都是一个异步数据的操作
        *demolink({payload},{put,call}){
            // 先把请求引用进来
            // 使用请求call 用来包裹数据请求 会返回出成功的结果
          let data=yield call(apilink)
          console.log(data)
          
        }
    }
   
  
  };
  

4.把请求来的数据交给reducers进行state的修改

// 引用请求封装
import {apilink} from "../services/example.js"
export default {

    namespace: 'homem',
  
    state: {
        name:"xixi",
        age:18
    },
    // 数据修改
    reducers:{
        // 每一个函数就是一个数据的修改动作
        // state 数据源
        // payload 就是外部传递进来的数据
        demoa(state,payload){
            // 在函数中返回一个修改之后的结果
            return {...state,age:666}
        },
        demob(state,payload){
            // console.log(payload.data)
            return {...state,age:payload.data.text}
        },
    },
    // 进行异步数据的操作
    effects:{
        // 对应的都是一个个的方法(Generator函数)  每个方法都是一个异步数据的操作
        *demolink({payload},{put,call}){
            // 先把请求引用进来
            // 使用请求call 用来包裹数据请求 会返回出成功的结果
          let data=yield call(apilink)
          console.log(data.data.data)
        //   把请求来的数据交给reducers来修改 我们在effect中调用reducer使用put来触发
          yield put({
              type:"update",//put是调用reducer的  type就是调用的reducer名字
              data:{
                  arr:data.data.data
              }
            })

        }
    }
   
  
  };
  

5.编写对应的reducer 来进行state的修改

// 引用请求封装
import {apilink} from "../services/example.js"
export default {

    namespace: 'homem',
  
    state: {
        name:"xixi",
        age:18,
        arr:[]
    },
    // 数据修改
    reducers:{
        // 每一个函数就是一个数据的修改动作
        // state 数据源
        // payload 就是外部传递进来的数据
        demoa(state,payload){
            // 在函数中返回一个修改之后的结果
            return {...state,age:666}
        },
        demob(state,payload){
            // console.log(payload.data)
            return {...state,age:payload.data.text}
        },

        // 进行state的数据修改
        update(state,payload){
            return {...state,arr:payload.data.arr}
        }
    },
    // 进行异步数据的操作
    effects:{
        // 对应的都是一个个的方法(Generator函数)  每个方法都是一个异步数据的操作
        *demolink({payload},{put,call}){
            // 先把请求引用进来
            // 使用请求call 用来包裹数据请求 会返回出成功的结果
          let data=yield call(apilink)
          console.log(data.data.data)
        //   把请求来的数据交给reducers来修改 我们在effect中调用reducer使用put来触发
          yield put({
              type:"update",//put是调用reducer的  type就是调用的reducer名字
              data:{
                  arr:data.data.data
              }
            })

        }
    }
   
  
  };
  

6页面获取数据

import React, { Component } from 'react'
import {connect} from "dva"
class phone extends Component {
    componentDidMount() {
        // 触发effects进行数据请求
        this.props.dispatch({type:"homem/demolink"})
    }
    
    render() {
        return (
            <div>
                {/* 读取数据 */}
                <h1>dva数据请求闭环操作---{this.props.state.homem.arr}</h1>
            </div>
        )
    }
}
export default connect(state=>({state}))(phone)
 类似资料: