目录

一:分层

二:使用DVA进行数据分层管理

三:在model中请求数据

四:mock数据


一:分层

       上图中,左侧是服务端代码的层次结构,由 Controller 、 Service 、 Data Access 三层组成服务端系统:
  • Controller 层负责与用户直接打交道,渲染页面、提供接口等,侧重于展示型逻辑。
  • Service 层负责处理业务逻辑,供 Controller 层调用。
  • Data Access 层顾名思义,负责与数据源对接,进行纯粹的数据读写,供 Service 层调用。
上图的右侧是前端代码的结构,同样需要进行必要的分层:
  • Page 负责与用户直接打交道:渲染页面、接受用户的操作输入,侧重于展示型交互性逻辑。
  • Model 负责处理业务逻辑,为 Page 做数据、状态的读写、变换、暂存等。
  • Service 负责与 HTTP 接口对接,进行纯粹的数据读写。

二:使用DVA进行数据分层管理

      dva 是基于 redux 、 redux-saga 和 react-router 的轻量级前端框架。官网: https://dvajs.com/
      对于 dva 我们不做过多详细的讲解,我们只要做到能够使用起来就可以了。对于想要全面学习 dva 框架的同学可自 行研究。
     首先,我们先将 dva 框架引入进来,由于 umi 对 dva 进行了整合,所以导入就变得非常简单了。

在confifig.js文件中进行配置:

export default {
plugins: [['umi-plugin-react', {dva: true // 开启dva功能}]
]
};
        接下来,创建 model 文件,在 umi 中,约定在 src/models 文件夹中定义 model ,所以,在该文件夹下创建
ListData.js 文件:

编写内容:

export default {
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) => {const listData = state[namespace].data;
return {listData
};
};@connect(mapStateToProps)
class List extends React.Component{render(){return (
<div>
<ul>
{
// 遍历值
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;
测试:

可以看到,效果是一样的。

流程说明:
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 中的数据
刚刚只是将数据展现出来,如果点击按钮,需要修改 state 的值,怎么操作呢?
首先,在 model 中新增 reducers 方法,用于更新 state 中的数据:
export default {
namespace: 'list',
state: {
data: [1, 2, 3],
maxNum: 3
},
reducers : {
addNewData(state){ //state是更新前的对象
let maxNum = state.maxNum + 1;
let list = [...state.data, maxNum];
return { // 返回更新后的state对象
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
onClick={()=>{this.props.addNewData()}}>
添加
</button>
</div>
);
}
}
export default List;
测试:

测试结果,和之前实现效果一样。
流程梳理如下:

三:model中请求数据

        前面我的数据是写死在 model 中的,实际开发中,更多的是需要异步加载数据,那么在 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: 0
},reducers: {
addNewData(state, result) { //result就是拿到的结果数据
if(result.data){ //判断result中的data是否存在,如果存在,说明是初始化数据,直接返回
return result.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回来的数据
});
}
}
}
改造页面逻辑:

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) => {return {
addNewData : () =>{dispatch({
type: namespace + "/addNewData"
});
},initData : () => { //新增初始化方法的定义
dispatch({
type: namespace + "/initData"
});
}
}
}
@connect(mapStateToProps, mapDispatchToProps)
class List extends React.Component{
componentDidMount(){
this.props.initData(); //组件加载完后进行初始化操作
}
render(){
return (
<div>
<ul>
{
// 遍历值
this.props.listData.map((value,index) => {
return <li key={index}>{value}</li>
})
}
</ul>
<button
onClick={()=>{this.props.addNewData()}}>
添加
</button>
</div>
);
}
}export default List;
测试:

测试结果,发现会报错,原因是返回的数据不是 json 导致,解析出错。
查看下请求:

可以看到,返回的是html代码,所以会导致出错。

完整的List.js页面代码:

import React from 'react';
import { connect } from 'dva';const namespace = "list";// 说明:第一个回调函数,作用:将page层和model层进行链接,返回modle中的数据
// 并且,将返回的数据,绑定到this.props// 接收第二个函数,这个函数的作用:将定义的函数绑定到this.props中,调用model层中定义的函数
@connect((state) => {return {dataList : state[namespace].data,maxNum : state[namespace].maxNum}
}, (dispatch) => { // dispatch的作用:可以调用model层定义的函数return { // 将返回的函数,绑定到this.props中add : function () {dispatch({ //通过dispatch调用modle中定义的函数,通过type属性,指定函数命名,格式:namespace/函数名type : namespace + "/addNewData"});},init : () => {dispatch({ //通过dispatch调用modle中定义的函数,通过type属性,指定函数命名,格式:namespace/函数名type : namespace + "/initData"});}}
})
class  List extends React.Component{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;

完整的ListData.js页面代码:

import request from '../util/request';export default {namespace: 'list',state: {data: [],maxNum: 1},reducers : { // 定义的一些函数addNewData : function (state, result) { // state:指的是更新之前的状态数据, result: 请求到的数据if(result.data){ //如果state中存在data数据,直接返回,在做初始化的操作return result.data;}let maxNum = state.maxNum + 1;let newArr = [...state.data, maxNum];return {data : newArr,maxNum : maxNum}//通过return 返回更新后的数据}},effects: { //新增effects配置,用于异步加载数据*initData(params, sagaEffects) { //定义异步方法const {call, put} = sagaEffects; //获取到call、put方法const url = "/ds/list"; // 定义请求的urllet data = yield call(request, url); //执行请求yield put({ // 调用reducers中的方法type : "addNewData", //指定方法名data : data //传递ajax回来的数据});}}
}

完整的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();
}

四:mock数据

umi 中支持对请求的模拟,由于我们现在没有真正的服务可以返回数据,所以才需要模拟。
在项目根目录下创建 mock 目录,然后创建 MockListData.js 文件,并且输入如下内容:

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

发现,可以正常返回数据了。
页面效果也正常了 :

ReactJS入门之Model层相关推荐

  1. ReactJS入门之Model分层的概念

    分层 上图中,左侧是服务端代码的层次结构,由 Controller.Service.Data Access 三层组成服务端系统: Controller 层负责与用户直接打交道,渲染页面.提供接口等,侧 ...

  2. ReactJS入门之前端开发的演变

    ReactJS入门 前端开发的演变 到目前为止,前端的开发经历了四个阶段,目前处于第四个阶段.这四个阶段分别是: 阶段一:静态页面阶段 在第一个阶段中前端页面都是静态的,所有前端代码和前端数据都是后端 ...

  3. php 实现 model层,Thinkhphp5控制器调用的Model层的方法总结

    控制器器里: /** * Created by PhpStorm. * User: Haima * Date: 2018/7/8 * Time: 15:58 */ namespace app\api\ ...

  4. ReactJS入门学习一

    ReactJS入门学习一 阅读目录 React是什么? React如何制作组件? 理解组件属性props 理解页面中如何渲染数据的 理解从服务器端获取数据及理解state的 回到顶部 React是什么 ...

  5. java 框架 Dao层 Mapper层 controller层 service层 model层 entity层 简介

    目录 简介 entity层 mapper层 service层 controller层 简介 SSM是sping+springMVC+mybatis集成的框架. MVC即model view contr ...

  6. view,control,service,dao,model层的关系

    view层:    结合control层,显示前台页面. control层:业务模块流程控制,调用service层接口. service层:业务操作实现类,调用dao层接口. dao层:     数据 ...

  7. Model层的两种写法

    Model层的两种写法 第一种写法 namespace MyMVC.Models {public class Child{ //属性private int id;public int Id{get { ...

  8. java的model层实例_Struts 2.1.6 精简实例系列教程(3):新闻管理Model层的开发(整合iBatis)...

    本期开始讲Model层的开发,整合iBatis框架,iBatis是Apache旗下Java数据持久层的框架,跟Hibernate是同一类型的框架.大家可到它的官方网站去下载http://ibatis. ...

  9. koa --- [MVC实现之五]Model层的实现

    说明 上一篇: MVC实现之四 这一篇主要介绍: 项目中用到的Sequelize库中的一些方法,参考使用Sequelize连接mysql 将Model层加入Mar类中 Service层 还是从业务出发 ...

最新文章

  1. CCF关于对NOIP2018复赛违规处罚的公告
  2. Servlet 过滤器
  3. 经典C语言程序100例之九一
  4. 程序员,你是真的该养生了
  5. Table 'barfoo_datacenter_config.parttemplates' doesn't exist------Mysql
  6. mysql安装与配置的截图_windows下MySQL5.6版本安装及配置过程附有截图和详细说明...
  7. PHP超级全局变量总结
  8. 一次mongoengine查询速度慢的优化
  9. HttpUtility.UrlEncode 方法
  10. 团队开发——用户需求报告
  11. python_paramiko模块
  12. DNF怎么查看服务器状态,dnf显示服务器读取中进不去怎么办 dnf显示服务器读取中进不去解决方法...
  13. 条形码、二维码、三维码解读
  14. 网络工程师--网络规划和设计案例分析(4)
  15. 内外兼修的移动办公伴侣:联想YOGA S730评测体验
  16. Unity游戏开发 头发飘动效果
  17. w7计算机开机密码怎么设置,如何设置电脑开机密码,图文教你怎么设置开机密码(winxp/win7)...
  18. Java解析excel工具easyexcel 助你快速简单避免OOM
  19. 用U盘做系统安装盘的极简方法
  20. Matlab-算术编码

热门文章

  1. 申请国家标准项目管理专业人员能力评级(CSPM)报名条件有哪些?
  2. javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
  3. 5000字 大数据时代读书笔记_读书笔记 大数据时代
  4. SqlServer聚集索引原理
  5. CRM下午茶(19)-电子商务中的客户关系管理
  6. 浅水声信道模型的建立(3)----只考虑海面海底一次散射,多亮点研究
  7. 纸质实验记录本难合规,ELN电子实验记录本是必备
  8. git报错: HEAD detached from origin/master
  9. 南陵中学2021高考成绩查询,南陵中学2020年高考成绩喜报 一本达线人数816人
  10. Microsoft Office PowerPoint 2007教程