vue项⽬快速实现后端接⼝返回的xml格式的数据进⾏解析相关背景:
⽼项⽬重构,后端返回xml格式数据。
前端有现有的vue项⽬底层框架可以复⽤,现有框架⽀持对后端返回的json数据进⾏解析,需要调整的就是对xml格式数据的解析。前端对后端接⼝的请求使⽤axios进⾏封装,且有mock数据⽅便本地联调开发。
后端字符串转数组解决⽅案:
封装xml解析相关⽅法;
根据后端接⼝返回数据格式边写xml⽂件进⾏后端数据mock;
mock数据的实现:
json格式的数据可以直接编写json格式的数据进⾏模拟,可以很⽅便的进⾏解析。
xml格式的数据如果直接写成字符串格式的,更新管理起来会⽐较⿇烦,因此可以直接编写xml⽂件进⾏模拟。
对于mock接⼝数据的xml⽂件,可以在mock数据请求封装中直接对xml⽂件进⾏读取解析。
xml解析相关函数封装:
xmlLoad.js
1/**
2 * 加载xml⽂件
3 * @param {Object} dname
4*/
5function loadXMLDoc(dname) {
6 let xhttp
7if (window.XMLHttpRequest) {
8 xhttp = new XMLHttpRequest();
9 } else {
10 xhttp = new ActiveXObject("Microsoft.XMLHTTP");
11 }
12 xhttp.open("GET", dname, false);
13 xhttp.send();
sponseXML;
15 }
16
17/**
18 * xml字符串转换xml对象数据
19 * @param {Object} xmlStr
20*/
21function xmlStr2XmlObj(xmlStr) {
22var xmlObj = {};
23if (document.all) {
24var xmlDom = new ActiveXObject("Microsoft.XMLDOM");
25 xmlDom.loadXML(xmlStr);
26 xmlObj = xmlDom;
27 } else {
28 xmlObj = new DOMParser().parseFromString(xmlStr, "text/xml");
29 }
30return xmlObj;
31 }
32
33/**
34 * xml直接转换json数据
35 * @param {Object} xml
36*/
37function xmlObj2json(xml) {
38try {
39var obj = {};
40if (xml.children.length > 0) {
41for (var i = 0; i < xml.children.length; i++) {
42var item = xml.children.item(i);
43var nodeName = deName;
44if (typeof(obj[nodeName]) == "undefined") {
45 obj[nodeName] = xmlObj2json(item);
46 } else {
47if (typeof(obj[nodeName].push) == "undefined") {
48var old = obj[nodeName];
49 obj[nodeName] = [];
50 obj[nodeName].push(old);
51 }
52 obj[nodeName].push(xmlObj2json(item));
54 }
55 } else {
56 obj = Content;
57 }
58return obj;
59 } catch (e) {
60 console.ssage);
61 }
62 }
63
64/**
65 * xml字符串转换json数据
66 * @param {Object} xml
67*/
68function xmlStr2json(xml) {
69var xmlObj = xmlStr2XmlObj(xml);
70var jsonObj = {};
71if (xmlObj.childNodes.length > 0) {
72 jsonObj = xmlObj2json(xmlObj);
73 }
74return jsonObj;
75 }
76
77 export default {
78 loadXMLDoc,
79 xmlStr2XmlObj,
80 xmlObj2json,
81 xmlStr2json
82 }
mock后端返回数据:
<?xml version="1.0" encoding="utf-8"?>
<Apilist>
<!--⾸页banner-->
<searchBanners>
<ApiResult>
<ret_code>000000</ret_code>
<ret_msg>请求成功</ret_msg>
<datas>
<Banner>
<banner_id>001</banner_id>
<set_id>001</set_id>
<num>0</num>
<pic_url>xxx.jpg</pic_url>
<link_type>0</link_type>
<link_id>xxx</link_id>
<description>描述</description>
</Banner>
<Banner>
<banner_id>002</banner_id>
<set_id>002</set_id>
<num>0</num>
<pic_url>xxx.jpg</pic_url>
<link_type>1</link_type>
<link_id>/myTask</link_id>
<description>描述</description>
</Banner>
</datas>
</ApiResult>
</searchBanners>
...
</Apilist>
如上,⾼亮部分的标签可以看做是mock接⼝的名称,与前端对接⼝请求的封装函数名对应,如下:request.js
import request from '@api/request'
const {
errorToast,
http
} = request
/**
* 导出接⼝请求
* noNeedLogin: true ⽆需登录
* noPreError: true ⽆需预处理错误信息
*/
export default {
//检验⽤户登录有效性
searchBanners(params) {
return http({
api: "searchBanners",
data: params
})
},
......
注:经验证,xml⽂件需要放在static⽂件夹中,本地编译vue项⽬后,能直接在浏览器中访问该⽂件,以便于xml⽂件的读取。xml⽂档中mock数据的读取:
request.js
1 import axios from "axios"
2 ......
3 import xmlLoad from '@assets/js/xmlLoad'
4/**
5 * 封装mock数据模拟接⼝请求
6*/
7 let http2;
8if (isLocal) http2 = (params) => {
9var self = this
10 let dname = igin + '/l'
11return new Promise((resolve, reject) => {
12//读取xml中的数据
13 let xmlNodes = xmlLoad.loadXMLDoc(dname) //xml数据读取
14if(!xmlNodes) return;
15 let xmlJson = lObj2json(xmlNodes) //xml转换为json格式数据
16 let mocklist = xmlJson['Apilist'] //mock数据列表
17 setTimeout(() => {
18//获取当前访问接⼝名及mock数据
19 let key = params.api
20var data = mocklist[key].ApiResult
21 resolve(data)
22 })
23 }
24
25 export default {
26 errorToast,
27 http: isLocal ? http2 : http
28 }
后端接⼝真实数据的读取:
request.js
1 import axios from "axios"
2 import xmlLoad from '@assets/js/xmlLoad'
3 ......
4
5/**
6 * 封装服务器端接⼝请求⽅法
7*/
8 const http = (params) => {
9return new Promise((resolve, reject) => {
10 quest({
11 url: '/xxxx.do',//后端访问接⼝地址
12 params: params.data,
13 method: hod || 'POST'
14 }).then(function(res) {
15//解析接⼝返回的xml字符串数据
16 let xmlStr = res.data;
17 let xmlJson = lStr2json(xmlStr)
18 let data = xmlJson && xmlJson["ApiResult"]
19if (res.status == 200 && data) {
20 ......
21 resolve(data)
22 } else {
23 errorToast();
24 console.log(data)
25 }
26 }).catch(function(e) {
27 errorToast();
28 reject(e)
29 });
30 })
31 }
32
33/**
34 * 封装mock数据模拟接⼝请求
35*/
36 let http2;
37 ......
38
39 export default {
40 errorToast,
41 http: isLocal ? http2 : http
42 }
如上,即实现了对后端接⼝数据的模拟,⽅便本地开发,同时对xml格式数据处理⽅⾯也只是在请求封装中进⾏,页⾯中的实现未受影响。注意事项:
对于xml到json的转换,因xml本⾝并没有数组的概念,所以需要注意我们需要的“数组”如果只有⼀条数据的异常处理。
1<datas>
2<UserTask>
3<task_tag>001</task_tag>
4<task_term>001</task_term>
5<task_title>xxxx</task_title>
6<task_status>0</task_status>
7<task_extra_info>{"tag_name":"xxxx","tag_pic_url":"xxxx.jpg","task_begin_time":"2020.06.20","
task_end_time":"2020.07.20"}</task_extra_info>
8</UserTask>
9</datas>
如上⾯代码,如果只有⼀个 UserTask ,那么解析出来将是⼀个Object对象:
//只有⼀个UserTask
data:{
UserTask:{
......
}
}
如果有多个,则是数组:
/
/有多个UserTask
data:{
UserTask:[{
......
},{
......
},{
......
}]
}
对于这个情况,可以封装⼀个函数进⾏转换,以⽅便前端进⾏页⾯布局与数据渲染。代码如下:
1/**
2 * xml解析后的列表转换为js的数组
3 * @param {Object} xmlList
4*/
5function xmlListToArr(xmlList) {
6 let targetArr = []
7if (structor == Array) {
8 targetArr = xmlList
9 } else {
10 targetArr[0] = xmlList
11 }
12return targetArr
13 }
如上,可以封装在公共函数⾥边,在页⾯中有从后端请求的列表数据需要渲染时,就可以调⽤这个函数进⾏数据处理。
这⾥还需要注意这些问题:
⼤部分列表数据都需要进⾏数组化处理:毕竟⼤部分列表的数据都当然,如果是⼏个简单的图⽚列表的展⽰,那可以考虑单个图⽚的展⽰,不必要把单个图⽚也转换成数组;
数组化处理操作在具体页⾯具体业务代码中进⾏:列表数据的处理由于xml中没有数组的概念,所以没办法很好的进⾏集中封装处理,因此可以在具体页⾯的具体数据进⾏处理;
可以集中封装处理的情况:如果知道后端返回接⼝所有列表类数据都严格包含某个字符串,如list,那么可以直接在xml解析函数中进⾏拦截处理就好了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论