ReactJS入门之Model层
- 电脑硬件
- 2025-08-20 23:51:01

目录
一:分层
二:使用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 的轻量级前端框架。官网: dvajs / 对于 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"; // 定义请求的url let 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层由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“ReactJS入门之Model层”
上一篇
个人博客系统(前后端分离)
下一篇
Ansible剧本使用