基于前后端分离的开发方式,后端只需提供 api 接口,前端负责数据展示和交互实现。
对于前端开发来说,一个比较大的问题是,api 接口数据不能较早的获得,那么只能使用模拟数据。前端模拟数据可有如下思路:
1. 使用临时的数据获取方法替代 ajax 接口请求,联调时修改数据获取方式;
2. 使用代理方式,代理转发到本地模拟文件或模拟接口;
3. 在前端截获接口请求,针对性处理后返回数据。
方法一在简单的开发调试中比较方便快捷,但涉及接口和数据较多时,管理起来比较麻烦。
方法二是一种不错的方式,模拟和联调时前端代码均保持一致,但需要对后端接口请求进行代理配置,操作上相对复杂。
你可以将接口请求代理转发到本地服务,本地服务针对不同的接口返回不同的数据。这里推荐一个不错的前端开发代理调试工具: fidder(http://www.telerik.com/fiddler)
方法三即是这里要介绍的 jquery-mockjax 所实现的方式。
使用 jquery-mockjax
jquery-mockjax 是一个 jquery 插件,它可以截获 ajax 请求,匹配后模拟返回 ajax 响应。
使用 jquery-mockjax 可简单概括为三个步骤。
1. 在协调好数据接口后,准备好需模拟的接口和模拟数据配置。
2. 在应用请求发生前执行模拟。
3. 在后端正式接口上线/联调时,去掉模拟。
举个例子。如一个页面有一个列表请求如下:
/get/article/list
那么,我们可以新建一个文件 lzw-mockajx.js,内容写为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | var config = [{ url: '/get/article/list' , responseText: { code: 200, value: [] }, response: function (rq) { console.log(rq.data); for ( var i = 0; i < 25; i++) { this .responseText.value.push({ id: i + 1, title: 'test jquery mockajx_' + i, author: 'lzw.me' , dateTime: new Date().getTime() }); } } }]; for ( var i = 0, len = config.length; i < len; i++) { $.mockajx(config[i]); } |
示例页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <! doctype html> < html lang = "zh-cn" > < head > < meta charset = "utf-8" > < title >jquery-mockajx 示例</ title > < script src = "lzw-mockajx.js" ></ script > < script type = "text/javascript" > $.post('/get/article/list', {pageSize: 10, page:2}, function (result) { console.log('result: ', result); } </ script > </ head > < body > </ html > |
从 console 控制台中,浏览该页面,即可看到打印出来的 result 模拟数据。在与后端联调时,只需去掉 lzw-mockajx.js 的引用即可。
一个简单实用的使用方式介绍到这里就结束了,是否已经帮助到了你?jquery-mockjax 还提供了丰富的配置参数,请到如下地址详细了解:
https://github.com/jakerella/jquery-mockjax
最佳实践示例
丰富多样未必意味着最佳。如下示例代码展示了在过去的一段时间中,我使用 jquery-mockajx 的方式。它可以满足只详细定义关键接口、部分模拟、简单正则匹配等需求。
模型定义 mzMockjax.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | require( './jquery.mockjax' ); var responseConfig = {}; var mzMockjax = { mockjaxList: {}, //存储当前缓存的对象 render: function (restapiList, responseConfig) { this .getConfig(restapiList, responseConfig); return this ; }, /** * 主要配置项 * @param {Object} restapiList api 列表,用于通用定义 * @param {Object} detailConfig 详细的定义 */ getConfig: function (restapiList, detailConfig) { var item, len, options = {}; len = restapiList.length; //通用返回定义 for (item in restapiList) { if (! restapiList.hasOwnProperty(item)) { continue ; } options[item] = { url: restapiList[item], responseText: { "message" : "" , "value" : true , code: 200 } }; } //特殊接口定义义扩展 responseConfig = $.extend( true , options, detailConfig); return responseConfig; }, /** * 执行模拟 * @param {Object|String} list 允许模拟的url列表,包含 responseConfig 的键名的数组。当为字符串时,尝试作为正则匹配。当部分接口已开发完毕,则可从中移除。可选,无参时模拟所有接口 */ run: function (list) { var item, regex; $.extend( true , $.mockjaxSettings, { contentType: "application/json" }); if ( typeof list === 'string' ) { try { regex = new RegExp(list); } catch (e){ list = null ; } } for (item in responseConfig) { if (! responseConfig.hasOwnProperty(item)) { continue ; } if (!list || $.isArray(list) && $.inArray(item, list) !== -1 || regex && regex.test(item) ) { this .mockjaxList[item] = $.mockjax(responseConfig[item]); } } } }; //mzMockjax.run(['get_article_list', 'get_article_content']); module.exports = mzMockjax; |
使用接口模拟:
rest-list.js
1 2 3 4 5 6 7 | var restList = { get_article_list: '/rest/get/artice/list' , save_article_list: '/rest/save/artice' , get_article_content: '/rest/get/artice/content' }; module.exports = restList; |
config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | var config = { get_article_list: { responseText: { value: [] }, response: function (rq) { var i = 0, list = []; while (i++ < 10) { this .responseText.value.push({ id: i + 1, title: 'test jquery mockajx_' + i, author: 'lzw.me' , dateTime: new Date().getTime() }); } } } }; var mzMockjax = require( './mzMockjax' ); var restList = require( './rest-list' ); mzMockjax.render(restList, config) .run( '_article_' ); |