您的位置:首页 > Web前端 > Node.js

做省市区联动时,用node.js将数据调整到合适结构的两种常用方法

2017-06-18 19:27 369 查看

起因

省市区联动,或者城市名称匹配,是很常用的功能。在实现他们的时候,经常会出现这样的情况:拿到的行政区划数据 和 渲染所需要的结构 不相符。通常我会用JS把它们处理成合适的结构。

核心思路

遍历其子元素或属性,在遍历的回调函数中,通过临时对象,将数据重新组织成需要的结构,再将其push进一个新构建的数组中。遍历完成后,该数组就是想要的最后结果。

两种套路:数组 VS 对象。

对于数组和对象,有不同的遍历方式。

对于数组,视情况可用
map()
,
forEach()
filter()
等方法;


对于对象,可以结合使用
for in
Object.keys()
来遍历其属性。


注:
Object.keys()
可以返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)。

例子

1 数组:

test.js

const fs = require('fs')

//现有如下数组
const province = [{"code":"110000","name":"北京市"},{"code":"120000","name":"天津市"},{"code":"130000","name":"河北省"},{"code":"140000","name":"山西省"},{"code":"150000","name":"内蒙古自治区"},{"code":"210000","name":"辽宁省"},{"code":"220000","name":"吉林省"},{"code":"230000","name":"黑龙江省"},{"code":"310000","name":"上海市"},{"code":"320000","name":"江苏省"},
... ...
]

//用于放结果的空数组
let finalProvince = []

//要把数组改成这种格式
// let options = [{
//   value: '123435',
//   label: 'Zhejiang',
//   isLeaf: false,
// }, {
//   value: 'jiangsu',
//   label: 'Jiangsu',
//   isLeaf: false,
// }];

province.map(
item => {
let tempObj = {}
tempObj.label = item.name
tempObj.value = item.code
tempObj.isLeaf = false
finalProvince.push(tempObj)
}
);

console.log(finalProvince);

fs.writeFile('temp.js', JSON.stringify(finalProvince), (err) => {
if (err) throw err;
console.log('The file has been saved!');
})


运行

node test.js


temp.js
中得到所需的json格式的文件

2 对象:

const fs = require('fs')

const rawData = {
"北京市":{
"市辖区":["东城区","西城区","朝阳区","丰台区","石景山区","海淀区","门头沟区","房山区","通州区","顺义区","昌平区","大兴区","怀柔区","平谷区","密云区","延庆区"]
},
"天津市":{
"市辖区":["和平区","河东区","河西区","南开区","河北区","红桥区","东丽区","西青区","津南区","北辰区","武清区","宝坻区","滨海新区","宁河区","静海区","蓟州区"]
},
"河北省":{
"石家庄市":["长安区","桥西区","新华区","井陉矿区","裕华区","藁城区","鹿泉区","栾城区","井陉县","正定县","行唐县","灵寿县","高邑县","深泽县","赞皇县","无极县","平山县","元氏县","赵县","晋州市","新乐市"],
"唐山市":["路南区","路北区","古冶区","开平区","丰南区","丰润区","曹妃甸区","滦县","滦南县","乐亭县","迁西县","玉田县","遵化市","迁安市"],
"秦皇岛市":["海港区","山海关区","北戴河区","抚宁区","青龙满族自治县","昌黎县","卢龙县"],
"邯郸市":["邯山区","丛台区","复兴区","峰峰矿区","邯郸县","临漳县","成安县","大名县","涉县","磁县","肥乡县","永年县","邱县","鸡泽县","广平县","馆陶县","魏县","曲周县","武安市"],
"邢台市":["桥东区","桥西区","邢台县","临城县","内丘县","柏乡县","隆尧县","任县","南和县","宁晋县","巨鹿县","新河县","广宗县","平乡县","威县","清河县","临西县","南宫市","沙河市"],
"保定市":["竞秀区","莲池区","满城区","清苑区","徐水区","涞水县","阜平县","定兴县","唐县","高阳县","容城县","涞源县","望都县","安新县","易县","曲阳县","蠡县","顺平县","博野县","雄县","涿州市","安国市","高碑店市"],
"张家口市":["桥东区","桥西区","宣化区","下花园区","万全区","崇礼区","张北县","康保县","沽源县","尚义县","蔚县","阳原县","怀安县","怀来县","涿鹿县","赤城县"],
"承德市":["双桥区","双滦区","鹰手营子矿区","承德县","兴隆县","平泉县","滦平县","隆化县","丰宁满族自治县","宽城满族自治县","围场满族蒙古族自治县"],
"沧州市":["新华区","运河区","沧县","青县","东光县","海兴县","盐山县","肃宁县","南皮县","吴桥县","献县","孟村回族自治县","泊头市","任丘市","黄骅市","河间市"],
"廊坊市":["安次区","广阳区","固安县","永清县","香河县","大城县","文安县","大厂回族自治县","霸州市","三河市"],
"衡水市":["桃城区","冀州区","枣强县","武邑县","武强县","饶阳县","安平县","故城县","景县","阜城县","深州市"],
"省直辖县级行政区划":["定州市","辛集市"]
},
"山西省":{
"太原市":["小店区","迎泽区","杏花岭区","尖草坪区","万柏林区","晋源区","清徐县","阳曲县","娄烦县","古交市"],
"大同市":["城区","矿区","南郊区","新荣区","阳高县","天镇县","广灵县","灵丘县","浑源县","左云县","大同县"],
"阳泉市":["城区","矿区","郊区","平定县","盂县"],
"长治市":["城区","郊区","长治县","襄垣县","屯留县","平顺县","黎城县","壶关县","长子县","武乡县","沁县","沁源县","潞城市"],
"晋城市":["城区","沁水县","阳城县","陵川县","泽州县","高平市"],
"朔州市":["朔城区","平鲁区","山阴县","应县","右玉县","怀仁县"],
"晋中市":["榆次区","榆社县","左权县","和顺县","昔阳县","寿阳县","太谷县","祁县","平遥县","灵石县","介休市"],
"运城市":["盐湖区","临猗县","万荣县","闻喜县","稷山县","新绛县","绛县","垣曲县","夏县","平陆县","芮城县","永济市","河津市"],
"忻州市":["忻府区","定襄县","五台县","代县","繁峙县","宁武县","静乐县","神池县","五寨县","岢岚县","河曲县","保德县","偏关县","原平市"],
"临汾市":["尧都区","曲沃县","翼城县","襄汾县","洪洞县","古县","安泽县","浮山县","吉县","乡宁县","大宁县","隰县","永和县","蒲县","汾西县","侯马市","霍州市"],
"吕梁市":["离石区","文水县","交城县","兴县","临县","柳林县","石楼县","岚县","方山县","中阳县","交口县","孝义市","汾阳市"]
},
"内蒙古自治区":{
"呼和浩特市":["新城区","回民区","玉泉区","赛罕区","土默特左旗","托克托县","和林格尔县","清水河县","武川县"],
"包头市":["东河区","昆都仑区","青山区","石拐区","白云鄂博矿区","九原区","土默特右旗","固阳县","达尔罕茂明安联合旗"],
"乌海市":["海勃湾区","海南区","乌达区"],
"赤峰市":["红山区","元宝山区","松山区","阿鲁科尔沁旗","巴林左旗","巴林右旗","林西县","克什克腾旗","翁牛特旗","喀喇沁旗","宁城县","敖汉旗"],
"通辽市":["科尔沁区","科尔沁左翼中旗","科尔沁左翼后旗","开鲁县","库伦旗","奈曼旗","扎鲁特旗","霍林郭勒市"],
"鄂尔多斯市":["东胜区","康巴什区","达拉特旗","准格尔旗","鄂托克前旗","鄂托克旗","杭锦旗","乌审旗","伊金霍洛旗"],
"呼伦贝尔市":["海拉尔区","扎赉诺尔区","阿荣旗","莫力达瓦达斡尔族自治旗","鄂伦春自治旗","鄂温克族自治旗","陈巴尔虎旗","新巴尔虎左旗","新巴尔虎右旗","满洲里市","牙克石市","扎兰屯市","额尔古纳市","根河市"],
"巴彦淖尔市":["临河区","五原县","磴口县","乌拉特前旗","乌拉特中旗","乌拉特后旗","杭锦后旗"],
"乌兰察布市":["集宁区","卓资县","化德县","商都县","兴和县","凉城县","察哈尔右翼前旗","察哈尔右翼中旗","察哈尔右翼后旗","四子王旗","丰镇市"],
"兴安盟":["乌兰浩特市","阿尔山市","科尔沁右翼前旗","科尔沁右翼中旗","扎赉特旗","突泉县"],
... ...

}

//目标结构
// const options = [{
//   value: '浙江',
//   label: '浙江',
//   children: [{
//     value: 'hangzhou',
//     label: 'Hangzhou',
//     children: [{
//       value: 'xihu',
//       label: 'West Lake',
//     }],
//
//   }]
// }];

const finalArr = []

for (let prop of Object.keys(rawData)){
let tempObj = {}
tempObj.label = prop
tempObj.value = prop
tempObj.children = []

for (let pr of Object.keys(rawData[prop])){
let tempTempObj = {}
tempTempObj.label = pr
tempTempObj.value = pr

let tempTempArr = []

//最内层变成数组的了
rawData[prop][pr].map(
item => {
let tempTempTempObj = {}
tempTempTempObj.label = item
tempTempTempObj.value = item
tempTempArr.push(tempTempTempObj)
}
)

tempTempObj.children = tempTempArr
tempObj.children.push(tempTempObj)
}
finalArr.push(tempObj)

}
console.log(finalArr);

fs.writeFile('temp.js', JSON.stringify(finalArr), (err) => {
if (err) throw err;
console.log('The file has been saved!');
})


运行

node test.js


temp.js
中得到所需的json格式的文件

相关项目

React案例:省市县三级联动选择框

这两个例子中的目标数据结构,都是ant design 的省市区联动组件 Cascader级联选择 所需的。具体请查看链接

creat-react-app
跑起来效果如动图:



一个微信小程序的案例:城区联动选择器

为了减少文件体积,源码中只保存了省一级的数据,市县通过腾讯地图的API获取。具体请查看链接



参考文档

MDN Object.keys()

MDN for…in

JS遍历对象的属性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息