效果图

选中后返回数据:

[{"text":"浙江省","value":"330000"},{"text":"杭州市","value":"330100"},{"text":"萧山区","value":"330109"}]

简要步骤

  1. 下载uniapp提供的省市区数据 json文件,到项目中
  2. app的页面中引入json文件
  3. 一维数组转多维数组,树形结构,传给组件  “uni-data-picker
  4. 点击、获取省市区

完整示例.vue

 要求:
1)uniapp项目中已经装好uni-ui扩展组件,包含组件“uni-data-picker
2)uniapp项目中已存放好来自openDB的数据json文件 (opendb-city-china
     存放位置 /common/opendb-master/collection/opendb-city-china/data.json
     下载地址 https://gitee.com/dcloud/opendb

<template>
	<view>
		<uni-data-picker :localdata="localData" popup-title="请选择省市区" @change="onchange" @nodeclick="onnodeclick">
		</uni-data-picker>
	</view>
</template>

<script>
	
	const cityRows = require('@/common/opendb-master/collection/opendb-city-china/data.json')
	export default {
		data() {
			return {
				// 省市区
				localData: []
			}
		},
		
		onLoad() {
			// 省市区数据树生成
			this.localData = this.get_city_tree()
			// console.log(JSON.stringify(this.localData))
		},
		
		methods: {
			
			// 节点变化后 (并非已经选择完毕)
			onnodeclick(node) {
				// console.log(JSON.stringify(node))
			},
			
			// 整体选择完成以后
			onchange(e) {
				const value = e.detail.value
				console.log(JSON.stringify(value))
			},
			
			
			
			// 省市区数据树生成
			get_city_tree () {
				let res = []
				if (cityRows.length) {
					// 递归生成
					res = this.handleTree(cityRows)
				}
				return res
			},
			
			
			/**
			 * 递归生成树结构数据 - 省市区
			 * 
			 * @param {Object} data
			 * @param {String} parent_code 上级ID | null代表需要顶部菜单
			 * @author Rudon  https://rudon.blog.csdn.net/
			 * 
			 * 源数据:
			 * {
			 * 	  "code": "110100", 
			 *    "name": "北京市",
			 *    "pinyin": "beijingshi",
			 *    "zip_code": "100000",
			 *    "parent_code": "110000",
			 *    "type": 1,
			 *    "first_letter": "B"
			 * }
			 * 
			 * 目标:
			 * {
			 *   text: "XX市",
			 *   value: "810000",
			 *   children: []
			 * }
			 * 
			 */
			handleTree (data, parent_code = null) {
				let res = []
				
				let keys = {
					id: 'code',
					pid: 'parent_code',
					children: 'children',
					
					text: 'name',
					value: 'code'
				}
				
				let oneItemDEMO = {
					text: '',
					value: '',
					children: []
				}
				let oneItem = {}
				
				// 循环
				for (let index in data) {
					// 判断
					if (parent_code === null) {
						// 顶级菜单 - 省
						if (!data[index].hasOwnProperty( keys.pid ) || data[index][keys.pid] == parent_code) {
							// 不存在parent_code,或者已匹配
							oneItem = JSON.parse(JSON.stringify(oneItemDEMO))
							oneItem.text = data[index][keys.text]
							oneItem.value = data[index][keys.value]
							
							// 递归下去
							oneItem.children = this.handleTree(data, data[index][keys.id])
							res.push(oneItem)
							
						} else {
							// 匹配不到,跳过
						}
						
					} else {
						// 非顶级菜单 - 市、区、街道
						if (data[index].hasOwnProperty( keys.pid ) && data[index][keys.pid] == parent_code) {
							// 已匹配
							oneItem = JSON.parse(JSON.stringify(oneItemDEMO))
							oneItem.text = data[index][keys.text]
							oneItem.value = data[index][keys.value]
							
							// 递归下去
							oneItem.children = this.handleTree(data, data[index][keys.id])
							res.push(oneItem)
							
						} else {
							// 匹配不到,跳过
						}
						
					}
					
				}
				
				return res
			}
		}
	}
</script>


<style>

</style>

格式约定

 uniapp省市区选择组件 “uni-data-picker” 需要的格式: (多维数组 text value children)

opendb-city-china/data.json 数据结构:(一维数组 code parent_code name)

详细步骤

... 见上面的完整实例

核心代码 - 递归生成省市区需要的多维数组:

handleTree (data, parent_code = null) {
    let res = []
    
    let keys = {
        id: 'code',
        pid: 'parent_code',
        children: 'children',
        
        text: 'name',
        value: 'code'
    }
    
    let oneItemDEMO = {
        text: '',
        value: '',
        children: []
    }
    let oneItem = {}
    
    // 循环
    for (let index in data) {
        // 判断
        if (parent_code === null) {
            // 顶级菜单 - 省
            if (!data[index].hasOwnProperty( keys.pid ) || data[index][keys.pid] == parent_code) {
                // 不存在parent_code,或者已匹配
                oneItem = JSON.parse(JSON.stringify(oneItemDEMO))
                oneItem.text = data[index][keys.text]
                oneItem.value = data[index][keys.value]
                
                // 递归下去
                oneItem.children = this.handleTree(data, data[index][keys.id])
                res.push(oneItem)
                
            } else {
                // 匹配不到,跳过
            }
            
        } else {
            // 非顶级菜单 - 市、区、街道
            if (data[index].hasOwnProperty( keys.pid ) && data[index][keys.pid] == parent_code) {
                // 已匹配
                oneItem = JSON.parse(JSON.stringify(oneItemDEMO))
                oneItem.text = data[index][keys.text]
                oneItem.value = data[index][keys.value]
                
                // 递归下去
                oneItem.children = this.handleTree(data, data[index][keys.id])
                res.push(oneItem)
                
            } else {
                // 匹配不到,跳过
            }
            
        }
        
    }
    
    return res
}

写在最后

顺手推荐下 我自用的百度精简版 - 无广告 (特别是手机端)

https://baidu.rudon.cn/

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐