react基础笔记 model分层

标签: js  react  

1.model分层

在这里插入图片描述

  • Page 负责与用户直接打交道:渲染页面、接受用户的操作输入,侧重于展示型交互
    性逻辑。
  • Model 负责处理业务逻辑,为 Page 做数据、状态的读写、变换、暂存等.
  • Service 负责与 HTTP 接口对接,进行纯粹的数据读写。

1.1.使用DVA进行数据分层管理

  • dva是基于 redux、redux-saga 和 react-router 的轻量级前端框架。官
    网:https://dvajs.com/

  • 首先,我们先将dva框架引入进来,由于umi对dva进行了整合,所以导入就变得非常简
    单了。
    在config.js文件中进行配置:

export default {
 dva: {}
};

1.1.1.获取model中的数据

接下来,创建model文件,在umi中,约定在src/models文件夹中定义model,所以,在该文件夹下创建ListData.js文件:

  • 编写内容:
export default {
	//命名空间,在dva管理下区分 各个model的唯一标识
	namespace: 'list',
	state: {
		data: [1, 2, 3],
		maxNum: 3
	}
}
  • 对List.js进行改造:
import React from 'react';
import { connect } from 'dva';
const namespace = 'list';

const mapStateToProps = (state) => {
	//通过state ,根据命名空间获取相应的数据并返回
	//此时数据是从model中获取并且重新定义了一个数据绑定在this.props中
	const listData = state[namespace].data;
	return {
		listData
	};
};
//定义一个函数,将model中的数据绑定到this.props中,将函数传入注解中
@connect(mapStateToProps)
class List extends React.Component{
	render(){
		return (
			<div>
				<ul>
				{
				// 遍历值,通过this.props获取到数据
				this.props.listData.map((value,index) => {
					return <li key={index}>{value}</li>
					})
				}
				</ul>
				<button
					onClick={()=>{ //为按钮添加点击事件
					// let maxNum = this.state.maxNum + 1;
					// let list = [...this.state.dataList, maxNum];
					// this.setState({ //更新状态值
					// dataList : list,
					// maxNum : maxNum
					// });
					}}>
					添加
				</button>
			</div>
		);
	}
}
export default List;

测试:
绑定数据到this.props中
在这里插入图片描述

流程说明:

  1. umi框架启动,会自动读取models目录下model文件,即ListData.js中的数据
  2. @connect修饰符的第一个参数,接收一个方法,该方法必须返回{},将接收到
    model数据
  3. 在全局的数据中,会有很多,所以需要通过namespace进行区分,所以通过
    state[namespace]进行获取数据
  4. 拿到model数据中的data,也就是[1, 2, 3]数据,进行包裹{}后返回
  5. 返回的数据,将被封装到this.props中,所以通过this.props.listData即可获取到
    model中的数据

1.1.2.修改model中的数据

  • 首先,在model中新增reducers方法,用于更新state中的数据:
export default {
    namespace: 'list',
    state: {
        data: [1, 2, 3],
        maxNum: 3
    },
    reducers: {
    	//在reducers中添加一个方法,修改state中的数据
        addNewData: function (state) {
            let maxNum = state.maxNum + 1;
            let list = [...state.data, maxNum];
            return  { //更新状态值
                data : list,
                maxNum : maxNum
            }
        }
    }
}
  • 接下来修改List.js新增点击事件
import React from 'react';
import { connect } from 'dva';
const namespace = 'list';
const mapStateToProps = (state) => {
    const listData = state[namespace].data;
    const maxNum = state[namespace].maxNum;
    return {
        listData, maxNum
    };
};
const mapDispatchToProps = (dispatch) => { // 定义方法,dispatch是内置函数
    return { //返回的这个对象将绑定到this.props对象中
        addNewData : () =>{ // 定义方法
            dispatch({ // 通过调用dispatch()方法,调用model中reducers的方法
                type: namespace + "/addNewData" // 指定方法,格式:namespace/方法名
        });
        }
    }
}
@connect(mapStateToProps, mapDispatchToProps) //mapDispatchToProps:函数,将方法映射到props中
class List extends React.Component{
    render(){
        return (
            <div>
                <ul>
                    {
						// 遍历值
                        this.props.listData.map((value,index) => {
                            return <li key={index}>{value}</li>
                        })
                    }
                </ul>
                <button
                	//此时可直接调用this.props中的addNewData方法
                    onClick={this.props.addNewData() }>
                    添加
                </button>
            </div>
        );
    }
}
export default List;

1.1.3.在model中请求数据

  • 首先,创建src下创建util目录,并且创建request.js文件,输入如下内容:(用于异步请
    求数据)
// import fetch from 'dva/fetch';
function checkStatus(response) {
    if (response.status >= 200 && response.status < 300) {
        return response;
    }
    const error = new Error(response.statusText);
    error.response = response;
    throw error;
}
/**
 * Requests a URL, returning a promise.
 *
 * @param {string} url The URL we want to request
 * @param {object} [options] The options we want to pass to "fetch"
 * @return {object} An object containing either "data" or "err"
 */
export default async function request(url, options) {
    const response = await fetch(url, options);
    checkStatus(response);
    return await response.json();
}
  • 然后,在model中新增请求方法:
import request from '../util/request';
export default {
    namespace: 'list',
    state: {
        data: [],
        maxNum: 1
    },
    reducers: {
    	//resp传入返回的数据
        addNewData: function (state,resp) {
            if (resp.data) {
                return resp.data;
            }
            let maxNum = state.maxNum + 1;
            let list = [...state.data, maxNum];
            return  { //更新状态值
                data : list,
                maxNum : maxNum
            }
        }
    },
    effects: { //新增effects配置,用于异步加载数据
        *initData(params, sagaEffects) { //定义异步方法
            const {call, put} = sagaEffects; //获取到call、put方法
            const url = "/ds/list"; // 定义请求的url
            let data = yield call(request, url); //执行请求,并接受返回值
            yield put({ // 调用reducers中的方法
                type : "addNewData", //指定方法名
                data : data //传递ajax回来的数据,
            });
        }
    }
}
  • 修改list.js中的逻辑
import React from 'react'
import { connect } from 'dva';


const namespace = "list";
@connect((state) => {
    return {
        dataList: state[namespace].data,
        maxNum: state[namespace].maxNum
    }
},(dispatch) => {
    return {
        add: function () {
            dispatch({
                type: namespace + "/addNewData"
            })
        },
        //将初始化方法映射到props中
        init: () => {
            dispatch({
                type: namespace + "/initData"
            })
        }
    }
})
class List extends React.Component{
    constructor(props){ // 构造参数中必须要props参数
        super(props); // 调用父类的构造方法
        // this.state = { // 初始化this.state
        //     dataList : [1,2,3],
        //     maxNum : 3
        // };
    }
    //组件加载完后进行初始化操作
    componentDidMount() {
        this.props.init();
    }

    render(){
        return (
            <div>
                <ul>
                    {
// 遍历值
                        this.props.dataList.map((value,index) => {
                            return <li key={index}>{value}</li>
                        })
                    }
                </ul>
                <button
                    onClick={this.props.add}>
                    添加
                </button>
            </div>
        );
    }
}
export default List;

1.1.4.mock模拟请求数据

在项目根目录下创建mock目录,然后创建MockListData.js文件,并且输入如下内容:

export default {
    'get /ds/list': function (req, res) { //模拟请求返回数据
        res.json({
            data: [1, 2, 3, 4],
            maxNum: 4
        });
    }
}


当请求此路径时便可响应数据

版权声明:本文为lantian058原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lantian058/article/details/110678495

智能推荐

react脚手架-4

脚手架是什么? 一种工具,帮助快速生成项目的工程化结构,将所需要的工程环境配置好。 每个项目作出完成的效果不同,但是它们的基本工程化结构是相似的; 间接保证项目的基本结构的一致性,方便后期的维护。 Vue的脚手架:vue-cli Angular的脚手架:angular-cli React的脚手架:create-react-app 这些脚手架需要依赖什么呢? 这些脚手架都是用node编写的,都是基于...

CTF-Web-[极客大挑战 2019]BabySQL

CTF-Web-[极客大挑战 2019]BabySQL 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!本文仅用于学习与交流,不得用于非法用途! CTP平台 网址 https://buuoj.cn/challenges 题目 Web类,[极客大挑战 2019]BabySQL 打开题目的实例 思路 当然第一步还是尝试万能密码,然后...

delphi XE关于微信公众号支付及微信零钱支付的便捷解决方案

delphi XE关于微信公众号支付及微信零钱支付的便捷解决方案   一、需求        因为微信公众号支付需要接口开发支持,并且有些小微客户并不希望直接通过微信公众号支付到对公账户或小商户账户进行收单(因为那样会带来不菲的额外“手续费”支出),所以很多用户急切需要一种便捷而低成本的支付方案。    ...

20155209 20155230 《信息安全技术》实验四 木马及远程控制技术

索引: 实验目的 实验内容 实验步骤 思考题 实验体会 一、 实验目的 二、 实验内容 三、 实验步骤 实验主机 实验角色 主机B 木马被控端(木马服务器) 主机A 木马控制端(木马客户端) (一) 木马生成与植入 1. 生成网页木马 (1) 主机A首先通过Internet信息服务(IIS)管理器启动“木马网站”。 (2) 主机A进入实验平台在工具栏中单击“灰鸽...

【数据结构】顺序表(C语言)

顺序表 一.顺序表 1.结构定义 2.结构操作 2.1插入操作 2.2删除操作 3.代码演示 4.优化(malloc、calloc、realloc) 数据结构=结构定义+结构操作 一.顺序表 1.结构定义 结构定义主要包含下面3个方面: 存放数据的数组 顺序表的大小size 当前顺序表的长度(顺序表中的元素个数)length 2.结构操作 2.1插入操作 先将待插入位置后的数据整体往后平移一位 在...

猜你喜欢

CodeForces 1K-1600R-1407C Chocolate Bunny

1407C-Chocolate Bunny Description Link Analysis 题目概述 交互题 给出一个 1 → n 1\to n 1→n 的排列( 1 ≤ n ≤ 1 0 4 1\le n\le10^4 1≤n≤104),最多可以询问 2 n 2n 2n 次,对于每个询问 x , y x,y x,y,给出 a x   m o...

redhat Linux6下搭建Zabbix

Linux:6.2x86 IP地址:192.168.0.105 环境:Apache+MySQL+PHP 注意:Linux下安装zabbix需要有LAMP或者LNMP运行环境 搭建LAMP环境: 1、配置Apache 2、安装mysql 3、安装php 出现如下图所示的页面,说明服务安装正确 安装zabbix 1、将zabbix-2.0.3上传到/usr/local/src/目录下,并解压 2、新建...

2009年南海初中竞赛 约数

题目 解题思路 > [模拟] 代码...

Parameter 'userid' not found. Available parameters are [arg1, arg0, param1, param2]的解决办法

HTTP Status 500 – Internal Server Error Type 异常报告 消息 Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.bin...

h.264 aac librtmp推流应用

librtmp + h.264(MediaCodec) + aac(MediaCodec) + ams5 demo:https://github.com/wangzuxing/myrtmplive pc需安装ams5, 作为流服务器,android端通过pc端ip + ams5 rtmp端口跟流服务器建立连接(NetConnection) h.264: 摄像头预览数据 MediaCodec 编码(...